博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
thinkphp+redis实现秒杀功能
阅读量:4547 次
发布时间:2019-06-08

本文共 5149 字,大约阅读时间需要 17 分钟。

 

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

2,项目中实际使用redis

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

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

走到此处的时候秒杀的核心基本就完了,细节还需要自己在去完善,像购物车这边的处理还有订单的处理,好吧开始跑程序利用apache自身的ab可以进行简单的模拟并发测试如下:

 

跑起来,我擦跑步起来redis没有任何反应,此时还少一步重要的步骤就是开启redis服务,请根据自己的系统下一个redisbin_x32或者redisbin_x64的redis服务管理工具,点击redis-server.exe,ok至此全部完成如下图:

 

转载于:https://www.cnblogs.com/dawuge/p/10480825.html

你可能感兴趣的文章
(七十八)使用第三方框架INTULocationManager实现定位
查看>>
LeetCode问题:搜索插入位置
查看>>
JVM基础学习之基本概念、可见性与同步
查看>>
UML入门
查看>>
CodeForces - 524F And Yet Another Bracket Sequence
查看>>
python学习笔记-day10-2【多进程,多线程】
查看>>
Atitit 图像处理 平滑 也称 模糊, 归一化块滤波、高斯滤波、中值滤波、双边滤波)...
查看>>
Android Camera——拍照(转自http://vaero.blog.51cto.com/4350852/779942)
查看>>
Java Web项目移植
查看>>
11月的第一天
查看>>
2011简单总结
查看>>
android的Environment类,记录一下
查看>>
工作流Activiti5流程变量 任务变量 setVariables 跟 setVariablesLocal区别
查看>>
c语言诊断_断言库函数#include<assert.h>
查看>>
input type="file"获取文件名方法
查看>>
强力上攻后,缓解期结束,MACD死叉的案例
查看>>
Linux文件权限
查看>>
js替换字符串中特殊字符
查看>>
第一单元OO总结
查看>>
带分页的sql语句
查看>>