详解thinkphp+redis+队列的实现代码

 更新时间:2017年08月21日 15:00:11   作者:halay  
本篇文章主要介绍了thinkphp+redis+队列的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

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: 

<?php
/* 数据库配置 */
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:

/**
  * redis连接
  * @access private
  * @return resource
  * @author bieanju
  */
 private function connectRedis(){
  $redis=new \Redis();
  $redis->connect(C("REDIS_HOST"),C("REDIS_PORT"));  
  return $redis;
 }

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

//现在初始化里面定义后边要使用的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如下:

 /**
 * 访问产品前先将当前产品库存队列
 * @access public
 * @author bieanju
 */
 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 < $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一个库存队列,如果在就抛出,):

/**
  * 抢购商品前处理当前会员是否进入队列
  * @access public
  * @author bieanju
  */
 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 队列 */ 
  $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" => "系统繁忙,请重试!"));
  }
 }

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

 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队列已释放!");   
   }
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Laravel使用消息队列需要注意的一些问题

    Laravel使用消息队列需要注意的一些问题

    这篇文章主要给大家介绍了关于Laravel使用消息队列需要注意的一些问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起看看吧。
    2017-12-12
  • 基于PHP的登录和注册的功能的实现

    基于PHP的登录和注册的功能的实现

    这篇文章主要介绍了基于PHP的登录和注册的功能的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • php和腾讯直播的实现代码

    php和腾讯直播的实现代码

    这篇文章主要介绍了php和腾讯直播的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • PHP写的简单数字验证码实例

    PHP写的简单数字验证码实例

    下面小编就为大家带来一篇PHP写的简单数字验证码实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • PHP会员找回密码功能的简单实现

    PHP会员找回密码功能的简单实现

    下面小编就为大家带来一篇PHP会员找回密码功能的简单实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • thinkPHP交易详情查询功能详解

    thinkPHP交易详情查询功能详解

    这篇文章主要介绍了thinkPHP交易详情查询功能,结合实例形式分析了thinkPHP数据库查询功能及视图输出相关操作技巧,需要的朋友可以参考下
    2016-12-12
  • ThinkPHP中where()使用方法详解

    ThinkPHP中where()使用方法详解

    where方法可以用于对数据库操作的结果进行筛选。即SQL查询语句中的where子句。本文给大家介绍ThinkPHP中where()使用方法详解,感兴趣的朋友参考下
    2016-04-04
  • laravel实现一个上传图片的接口,并建立软链接,访问图片的方法

    laravel实现一个上传图片的接口,并建立软链接,访问图片的方法

    今天小编就为大家分享一篇laravel实现一个上传图片的接口,并建立软链接,访问图片的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • Yii2 输出xml格式数据的方法

    Yii2 输出xml格式数据的方法

    这篇文章主要介绍了Yii2 输出xml格式数据的方法的相关资料,小编感觉非常具有参考价值,特此分享到脚本之家平台,供大家参考
    2016-05-05
  • ThinkPHP的L方法使用简介

    ThinkPHP的L方法使用简介

    thinkPHP的L方法用于启用多语言的情况下,设置和获取当前的语言定义。这篇文章主要介绍了ThinkPHP的L方法使用简介,需要的朋友可以参考下
    2014-06-06

最新评论