zoukankan      html  css  js  c++  java
  • 详解thinkphp+redis+队列的实现代码(逻辑理解)

    https://www.jb51.net/article/121729.html     核心在于 队列只有一条 不会因查询   并发。

    1,安装Redis,根据自己的PHP版本安装对应的redis扩展(此步骤简单的描述一下)

    1.1,安装 php_igbinary.dll,php_redis.dll扩展此处需要注意你的php版本如图:

      

    1.2,php.ini文件新增 extension=php_igbinary.dll;extension=php_redis.dll两处扩展

    ok此处已经完成第一步redis环境搭建完成看看phpinfo

    项目中实际使用redis

    2.1,第一步配置redis参数如下,redis安装的默认端口为6379: 


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    return array(
     'DATA_CACHE_PREFIX' => 'Redis_',//缓存前缀
     'DATA_CACHE_TYPE'=>'Redis',//默认动态缓存为Redis
     'DATA_CACHE_TIMEOUT' => false,
     'REDIS_RW_SEPARATE' => true, //Redis读写分离 true 开启
     'REDIS_HOST'=>'127.0.0.1', //redis服务器ip,多台用逗号隔开;读写分离开启时,第一台负责写,其它[随机]负责读;
     'REDIS_PORT'=>'6379',//端口号
     'REDIS_TIMEOUT'=>'300',//超时时间
     'REDIS_PERSISTENT'=>false,//是否长连接 false=短连接
     'REDIS_AUTH'=>'',//AUTH认证密码
    );

    2.2,实际函数中使用redis:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     private function connectRedis(){
      $redis=new Redis();
      $redis->connect(C("REDIS_HOST"),C("REDIS_PORT")); 
      return $redis;
     }

    2.3,秒杀的核心问题是在大并发的情况下不会超出库存的购买,这个就是处理的关键所以思路是第一步在秒杀类的先做一些基础的数据生成:


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //现在初始化里面定义后边要使用的redis参数
    public function _initialize(){
      parent::_initialize();
      $goods_id = I("goods_id",'0','intval'); 
      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 = $this->user_id ? $this->user_id : $_SESSION['uid']; 
     }

    2.4,第二步就是关键所在,用户在进入商品详情页前先将当前商品的库存进行队列存入redis如下:


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public function _before_detail(){
     $where['goods_id'] = $this->goods_id;
     $where['start_time'] = array("lt",time());
     $where['end_time'] = array("gt",time());
     $goods = M("goods")->where($where)->field('goods_num,start_time,end_time')->find();
     !$goods && $this->error("当前秒杀已结束!");
     if($goods['goods_num'] > $goods['order_num']){
      $redis = $this->connectRedis();
      $getUserRedis = $redis->hGetAll("{$this->user_queue_key}");
      $gnRedis = $redis->llen("{$this->goods_number_key}");
      
      if(!count($getUserRedis) && !$gnRedis){  
       for ($i = 0; $i <</code> $goods['goods_num']; $i ++) {
        $redis->lpush("{$this->goods_number_key}", 1);
       }
      }
      $resetRedis = $redis->llen("{$this->goods_number_key}");
      if(!$resetRedis){
       $this->error("系统繁忙,请稍后抢购!");
      }
     }else{
      $this->error("当前产品已经秒杀完!");
     }
       
    }

    接下来要做的就是用ajax来异步的处理用户点击购买按钮进行符合条件的数据进入购买的排队队列(如果当前用户没在当前产品用户的队列就进入排队并且pop一个库存队列,如果在就抛出,):


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     public function goods_number_queue(){
      !$this->user_id && $this->ajaxReturn(array("status" => "-1","msg" => "请先登录"));
      $model = M("flash_sale");
      $where['goods_id'] = $this->goods_id;
      $goods_info = $model->where($where)->find();
      !$goods_info && $this->error("对不起当前商品不存在或已下架!");
      
      $redis = $this->connectRedis();
      
      $goods_number_key = $redis->llen("{$this->goods_number_key}");
      if (!$redis->hGet("{$this->user_queue_key}", $this->user_id)) {
       $goods_number_key = $redis->lpop("{$this->goods_number_key}");
      }
        
      if($goods_number_key){
       // 判断用户是否已在队列
       if (!$redis->hGet("{$this->user_queue_key}", $this->user_id)) {
        // 插入抢购用户信息
        $userinfo = array(
         "user_id" => $this->user_id,
         "create_time" => time()
        );   
        $redis->hSet("{$this->user_queue_key}", $this->user_id, serialize($userinfo));
        $this->ajaxReturn(array("status" => "1"));
       }else{
        $modelCart = M("cart");
        $condition['user_id'] = $this->user_id;
        $condition['goods_id'] = $this->goods_id;
        $condition['prom_type'] = 1;
      $cartlist = $modelCart->where($condition)->count();
        if($cartlist > 0){
         $this->ajaxReturn(array("status" => "2"));
        }else{
          
         $this->ajaxReturn(array("status" => "1"));
          
        }
          
       }
         
      }else{
       $this->ajaxReturn(array("status" => "-1","msg" => "系统繁忙,请重试!"));
      }
     }

    附加一个调试的函数,删除指定队列值:


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public function clearRedis(){
      set_time_limit(0);
      $redis = $this->connectRedis();
      //$Rd = $redis->del("{$this->user_queue_key}");
      $Rd = $redis->hDel("goods49",'用户id'');
      $a = $redis->hGet("goods_49_user", '用户id');
      if(!$a){
       dump($a);
      }
       
      if($Rd == 0){
       exit("Redis队列已释放!");  
      }
     }
  • 相关阅读:
    PyQt(Python+Qt)学习随笔:QTreeView树形视图的animated属性
    PyQt(Python+Qt)学习随笔:QTreeView树形视图的sortingEnabled属性
    PyQt(Python+Qt)学习随笔:QTreeView树形视图的itemsExpandable属性
    PyQt(Python+Qt)学习随笔:QTreeView树形视图的uniformRowHeights属性
    PyQt(Python+Qt)学习随笔:QTreeView树形视图的rootIsDecorated属性
    PyQt(Python+Qt)学习随笔:QTreeView树形视图的indentation属性
    PyQt(Python+Qt)学习随笔:QTreeView树形视图的autoExpandDelay属性
    第十五章、Model/View架构中Item Views部件的父类
    IIS断开连接之后internet信息服务里面不显示本地计算机的解决方法
    smarty模板引擎之if, elseif else
  • 原文地址:https://www.cnblogs.com/linewman/p/9918598.html
Copyright © 2011-2022 走看看