php商城秒杀,redis防高并发

 

<?php 

header('content-type:text/html;charset=utf-8');

class SeckillRedis {

    static protected $validity_time = 300; // 有效期 5分钟
    protected $goods_id;
    protected $user_queue_key;
    protected $goods_number_key;
    protected $user_id;


    public function __construct($goods_id,$area_id,$uid){
        if($goods_id){
            $this->goods_id=$goods_id;
            //当前商品队列的用户情况
            $this->user_queue_key="goods_".$goods_id."_user";
            //当前商品的库存队列
            $this->goods_number_key="goods_".$goods_id;
        }
        $this->user_id=$uid ? $uid : 2;
    }
 
    /* redis链接 */

    static public function getRedis(){
        $redis=new Redis();
        $redis->connect('127.0.0.1','6379') or die('Can not Content Redis');
        if($redis){
            return $redis;
        }else{
            die('Can not Content Redis!');
        }
    }

    // 添加或改变库存时初始化队列
    public function kuCun($num){
        $redis=$this->getRedis();
        $redis->delete($this->goods_number_key);
        // $redis->delete($this->user_queue_key);
        for ($i=0; $i < $num; $i++) {

            $redis->rPush($this->goods_number_key, 1);

        }
    }

    // 判断未支付订单是否过期 ,定时更新秒杀商品入口人数

    public function poling_set_seckill_redis(){
        
        //exists检查key是否存在,存在返回1,不存在返回0,0也属于不存在的
        if($redis->exists($this->user_queue_key) == true){

            // 清除过期的使用数量

            $use_list = $redis->lRange($this->user_queue_key, 0, -1);
            // var_dump($use_list);
            foreach ($use_list as $k => $v) {

                $data = json_decode($v, true);

                if(time() - $data['time'] > self::$validity_time){

                    // 超过有效期 删除

                    $this->returnFree($k,$data['uid']);

                }

            }

        }

    }
 
    /* 获取空闲抢购--type:50 100 500 1000 */

    public function getFree(){

        if(empty($this->user_id)){

            return array('result' => false, 'message' => '抢购信息:用户ID不能为空');

        }

        $redis = self::getRedis();

        $result = $redis->lPop($this->goods_number_key);

        // var_dump($redis->lrange($seckill_array[$type]['free_key'],0,-1));
        if($result == true){

            // 添加使用数量

            $index = $redis->rPush($this->user_queue_key, json_encode(array('uid' => $this->user_id, 'time' => time()))) - 1;

            return array('result' => true, 'index' => $index);

        }else{

            return array('result' => false, 'message' => '抢购信息:被抢光啦');

        }

    }

    /* 返回空闲抢购--$index为键值 */

    public function returnFree($index,$uid){

        $redis = self::getRedis();

        $value = $redis->lGet($this->user_queue_key,$index);

        if(!empty($value)){

            $redis->lRem($this->user_queue_key, $value, 1);

            // 添加空闲数量

            $redis->rPush($this->goods_number_key, 1);

            // $sql语句,库存加1

            return array('result' => true);

        }else{

            return array('result' => false, 'message' => '抢购信息:不存在索引');

        }

    }

}


class Index{

    

    /* 某个需要控制并发的控制器方法 */

    public function getOrderInfo(){

        $miaosha=new SeckillRedis('3','123','2');
        // $miaosha->kuCun('100');
        $result = $miaosha->getFree();

        return $result;
        if($result['result'] == false){

            // 没有机会 返回错误信息

            return '网络繁忙,请重试';

        }

        // 处理数据库代码


    }
}

$hua = new Index;
var_dump($hua->getOrderInfo()).'<br>';
$redis=SeckillRedis::getRedis();

echo $redis->llen('goods_3');
var_dump($redis->lrange('goods_3',0,-1));
var_dump($redis->lrange('goods_3_user',0,-1));

尚在改进,如果有改进或者其他看法请留言,一同探讨

posted on 2018-08-07 17:28  泽一年  阅读(293)  评论(0编辑  收藏  举报

导航