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

作者:halay 时间:2024-05-11 10:08:34 

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

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

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

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

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

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

项目中实际使用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队列已释放!");  
  }
 }

来源:http://blog.csdn.net/weixin_29778143/article/details/54930282

标签:thinkphp,redis,队列
0
投稿

猜你喜欢

  • perl脚本实现限制ssh最大登录次数(支持白名单)

    2022-04-09 02:56:56
  • NumPy迭代数组的实现

    2022-01-03 14:07:37
  • TensorFlow入门使用 tf.train.Saver()保存模型

    2023-06-07 15:29:45
  • python中logging库的使用总结

    2022-10-29 09:36:28
  • Python yield的使用详解

    2021-07-17 22:23:29
  • Django项目实战之配置文件详解

    2023-08-13 19:28:07
  • Python代理抓取并验证使用多线程实现

    2022-07-10 07:04:19
  • MySQL 5数据库连接超时问题

    2009-12-29 10:23:00
  • php生成静态页面并实现预览功能

    2023-11-15 08:37:11
  • VsCode中ctrl+s后会在当前目录下自动生成dist目录的方法

    2023-04-25 09:19:41
  • 使用Python的SymPy库解决数学运算问题的方法

    2021-04-19 19:36:35
  • MySQL实现JDBC详细步骤

    2024-01-28 13:39:11
  • Python用requests库爬取返回为空的解决办法

    2021-10-30 04:54:29
  • 某年第一周开始日期sql实现方法

    2012-02-25 20:02:30
  • 使用PyInstaller库把Python程序打包成exe

    2023-11-27 17:40:28
  • JavaScript中诡异的delete操作符

    2024-04-10 16:15:33
  • 使用matplotlib创建Gif动图的实现

    2021-03-09 11:32:02
  • Python数学建模学习模拟退火算法多变量函数优化示例解析

    2021-05-07 09:36:37
  • 答题辅助python代码实现

    2022-06-30 19:57:35
  • Python中JsonPath提取器和正则提取器

    2022-08-27 14:12:20
  • asp之家 网络编程 m.aspxhome.com