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
<?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:

1
2
3
4
5
6
7
8
9
10
11
/**
  * 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,秒杀的核心问题是在大并发的情况下不会超出库存的购买,这个就是处理的关键所以思路是第一步在秒杀类的先做一些基础的数据生成:

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

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

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

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

详解thinkphp+redis+队列的实现代码的更多相关文章

  1. php_DWZ-JUI中碰到的问题解决方法详解(thinkphp+dwz)

    原文:php_DWZ-JUI中碰到的问题解决方法详解(thinkphp+dwz) 折腾了两天,dwz删除后,数据不能自动刷新,解决方案,直接看图  . 1. 删除.修改状态后无法刷新记录: 在dwz. ...

  2. 详解OJ(Online Judge)中PHP代码的提交方法及要点【举例:ZOJ 1001 (A + B Problem)】

    详解OJ(Online Judge)中PHP代码的提交方法及要点 Introduction of How to submit PHP code to Online Judge Systems  Int ...

  3. Java并发包源码学习系列:详解Condition条件队列、signal和await

    目录 Condition接口 AQS条件变量的支持之ConditionObject内部类 回顾AQS中的Node void await() 添加到条件队列 Node addConditionWaite ...

  4. HBase 协处理器编程详解,第二部分:客户端代码编写

    实现 Client 端代码 HBase 提供了客户端 Java 包 org.apache.hadoop.hbase.client.coprocessor.它提供以下三种方法来调用协处理器提供的服务: ...

  5. 【Redis】Redis事务详解,Redis事务支持回滚(不支持悲观锁)

    1.redis事物参考:https://baijiahao.baidu.com/s?id=1613631210471699441&wfr=spider&for=pc (php操作red ...

  6. Transformer各层网络结构详解!面试必备!(附代码实现)

    1. 什么是Transformer <Attention Is All You Need>是一篇Google提出的将Attention思想发挥到极致的论文.这篇论文中提出一个全新的模型,叫 ...

  7. Redis 详解 (二) redis的配置文件介绍

    目录 1.开头说明 2.INCLUDES 3.MODULES 4.NETWORK 5.GENERAL 6.SNAPSHOTTING 7.REPLICATION 8.SECURITY 9.CLIENTS ...

  8. 详解.Net消息队列(MSMQ)应用

    [IT168 技术文档]MSMQ是Windows 2000.Windows XP.Windows Server 2003的一个组件,并将继续包含在Windows Vista和以后的Windows服务器 ...

  9. thinkphp+redis+队列

    1,安装redis,根据自己的php版本安装对应的redis扩展(此步骤简单的描述一下) 1.1,安装 php_igbinary.dll,php_redis.dll扩展此处需要注意你的php版本如图: ...

随机推荐

  1. linux常用命令(7)cp命令

    cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...

  2. 前端常用资源地址: http://www.htmleaf.com/

    前端常用资源地址: http://www.htmleaf.com/

  3. java:shiro(认证,赋予角色,授权...)

    1.shiro(权限框架(认证,赋予角色,授权...)): readme.txt(运行机制): 1.从jsp的form中的action属性跳转到springmvc的Handler中(controlle ...

  4. Sqlserver实现故障转移 — AlwaysOn实现故障转移(4)

    目的:在已经加域的计算机上安装sqlserver2012,并配置系统级故障转移及数据库,实现AlwayOn. 域控的建立详见:https://www.cnblogs.com/xiaoerlang90/ ...

  5. SQLSERVER去除某一列的重复值并显示所有数据\DISTINCT去重\ISNULL()求SUM()\NOT EXISTS的使用

    进入正题,准备我们的测试数据 1.我们要筛选的数据为去除 GX 列的重复项 并将所有数据展示出来,如图所示: ' 2.这种情况下我们是不可以使用DISTINCT来去重的,我们可以来尝试一下: 首先,单 ...

  6. Django下orm学习 一对多

    概念说明 ORM:关系对象映射的全称是 Object Relational Mapping, 简称ORM SQLAlchemy: 是Python编程语言下的一款ORM框架,该框架建立在数据库API之上 ...

  7. DOM事件练习 I

    目录 input框动态显示事件 红绿灯模拟 顶部广告栏关闭 鼠标悬停IMG上时,更换另一张图片 悬浮框自动出现 模态框案例 input框动态显示事件 <head> <meta cha ...

  8. win10安装tensorflow (cpu版)

    前提: 下载anaconda,然后创建一个python虚拟环境: 命令: conda create -n tf_cpu python=3.6       # (tf_cpu  是这个虚拟环境的名字) ...

  9. JAVA第四周总结

    Java实验报告二 第一题 写一个名为Rectangle的类表示矩形.其属性包括宽width.高height和颜色color,width和height都是double型的,而color则是String ...

  10. Java基础(七)

    字符串String类 字符串的两个问题 构造方法 字符串池 字符串的内容不可变 比较方法 练习:模拟登陆 练习:模拟登陆(限制重试次数) 替换方法(敏感词过滤) 如果希望将字符串当中指定的部分进行替换 ...