编程学习网 > 数据库 > PHP高并发优化处理——redis层面详细步骤
2019
09-15

PHP高并发优化处理——redis层面详细步骤

php层面如何优化高并发?

redis层面:
(1)利用redis加锁机制处理setnx key value:将 key 的值设为 value,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。SETNX 是SET if Not eXists的简写。

<?php


class Lock

{

    private static $_instance ;

    private   $_redis;

    private function __construct()

    {

        $this->_redis =  new Redis();

        $this->_redis ->connect('127.0.0.1');

    }

    public static function getInstance()

    {

        if(self::$_instance instanceof self)

        {

            return self::$_instance;

        }

        return self::$_instance = new  self();

    }

    /**

     * @function 加锁

     * @param $key 锁名称

     * @param $expTime 过期时间

      */

    public function set($key,$expTime)

    {

        //初步加锁

        $isLock = $this->_redis->setnx($key,time()+$expTime);

        if($isLock)

        {

            return true;

        }

        else

        {

            //加锁失败的情况下。判断锁是否已经存在,如果锁存在且已经过期,那么删除锁。进行重新加锁

            $val = $this->_redis->get($key);

            if($val&&$val<time())

            {

                $this->del($key);

            }

            return  $this->_redis->setnx($key,time()+$expTime);

        }

    }

    /**

     * @param $key 解锁

     */

    public function del($key)

    {

        $this->_redis->del($key);

    }

}


$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root');

$lockObj = Lock::getInstance();  //单例模式

//判断是能加锁成功

if($lock = $lockObj->set('storage',10))

{

    $sql="select `number` from  storage where id=1 limit 1";

    $res = $pdo->query($sql)->fetch();

    $number = $res['number'];

    if($number>0)

    {

        $sql ="insert into `order`  VALUES (null,$number)";


        $order_id = $pdo->query($sql);

        if($order_id)

        {


            $sql="update storage set `number`=`number`-1 WHERE id=1";

            $pdo->query($sql);

        }

    }

    //解锁

    $lockObj->del('storage');


}

else

{

    //加锁不成功执行其他操作。

}

?>  


(2)利用reids消息队列处理高并发:队列是按先进先出的顺序来执行,需要用到 lpop、rpush、llen等方法

/**

*优惠券redis入库

**/

public function reload_quan(){

        $yhq_dom = Yhq_user_relation::i();

        $redis = Redis::i('redis');

        $redis->setOption( \Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE );

        for ($i=0;$i<100;$i++){

            $date_time = date('Y-m-d H:i:s',time());

            $res = $yhq_dom->add([

                'hd_id' => 3,

                'yhq_id'=> 19,

                'name'  => '满58减20',

                'create_time' => $date_time,

                'price' => 58,

                'yuanbao' => 20

            ]);

            if (!$res){

                $this->_error('添加第'.$i.'张优惠券时失败');

            }

            //在redis中存入数据

            $redis->rPush('yhq_relation',"{$i}");

        }

        $redis->expire('yhq_relation',1860);

        $this->_success('','库内添加优惠券成功');

    }

/**

*领取优惠券

**/

public function get_quan(){

    $redis = Redis::i('redis');

    $redis->setOption( \Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE );

    $start_time = date('Y-m-d 00:00:00',time());

    $stop_time = date('Y-m-d 23:59:59',time());

    //判断是否在抢购时间内

    //$start_string = mktime(12,0,0,date('m'),date('d')-date('w')+5,date('Y'));

    //$stop_string = mktime(23,59,59,date('m'),date('d')-date('w')+5,date('Y'));

    //$now_time = time();

    //if ($now_time<$start_string || $now_time>$stop_string){

    //    $this->_error('抢券时间未到,请稍后再来~');

    //}

    $len = $redis->lLen('yhq_relation');

    if ($len<1){

        $this->_error('优惠券已经抢光啦~');

    }else{

        //领取优惠券时判断用户是否真正领取

        $user_id = $this->_user_info()['accid'];

        $yhq_dom = Yhq_user_relation::i();

        $where = [

            'accid' => $user_id,

            'hd_id'  => 3,

            'yhq_id'=>19,

            'create_time' => [

                'between' => [$start_time,$stop_time]

            ]

        ];

        $result = $yhq_dom->where($where)->find();

        if($result){

            $this->_error('对不起,您已经领取过了哦~');

        }else{

            //用户领取优惠券

            $expire_time = date('Y-m-d H:i:s',(time()+259200));

            $sql = "select id from yhq_user_relation where hd_id = 3 and yhq_id=19 and create_time between '$start_time' and '$stop_time' and accid is NULL ORDER by create_time ASC ";

            $update_id = $yhq_dom->query($sql)[0]['id'];

            //双重判断是否已经领取完毕

            if (!$update_id){

                $this->_error('优惠券已经抢光了哦~');

            }

            $redis->lPop('yhq_relation');

            $res = $yhq_dom->update("id={$update_id}",['accid'=>$user_id,'expire_time'=>$expire_time]);

            if ($res){

                $this->_success('','领取成功');

            }else{

                $this->_error('领取失败,请查看网络连接');

            }

        }

    }

}

暂且就先到到这里,欢迎拍砖!

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取