多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
Redis列队处理抢购,秒杀 库存列队格式 , 四条数据表示商品库存数量为4 ``` array(4) { [0] => string(1) "1" [1] => string(1) "1" [2] => string(1) "1" [3] => string(1) "1" } ``` 原理, 用户访问该产品的时候设置队列库存 ,当用户点击支付的时候,生成订单,移除一个库存 , 当订单取消的时候增加一个库存 ``` ~~~ <?php namespace app\home\controller; use think\Db; /** * Class Redis * @package app\home\controller */ class Redis extends Common { public $goods_id; public $user_queue_key; public $goods_number_key; public $user_id; public $times; public function __construct() { parent::__construct(); $goods_id = input("goods_id", '0', 'intval'); if (!$goods_id) { $this->error('商品不存在'); } $this->user_id=11; if (!$this->user_id) { $this->error('请先登录'); } $this->times = time(); $this->goods_id = $goods_id; $this->user_queue_key = "goods_" . $goods_id . "_user";//当前商品队列的用户情况 $this->goods_number_key = "goods" . $goods_id;//当前商品的库存队列 } /* * redis连接 */ private function connectRedis() { $redis = new \Redis(); $redis->connect('127.0.0.1', '6379'); return $redis; } /* * 查看商品,生成商品库存列队 */ protected function judgment_goods() { $where = [ ['id', '=', $this->goods_id], ['start_time', '<', $this->times],//秒杀开始时间 ['end_time', '>', $this->times],//秒杀结束时间 ]; $goods = Db("goods111")->where($where)->find(); if (!$goods) { $this->error("当前秒杀已结束!"); } if ($goods['number'] <= 0) { $this->error("当前产品已经秒杀完!"); } return $goods; } /** * 访问产品前先将当前产品库存队列 * @access public * @author bieanju */ public function before_detail() { $goods = $this->judgment_goods(); $redis = $this->connectRedis(); $getUserRedis = $redis->lLen($this->user_queue_key); // 获取列队会员的数量 $gnRedis = $redis->lLen($this->goods_number_key); //获取商品库存数量 /* 如果没有会员进来队列库存 */ if (!$getUserRedis && !$gnRedis) { for ($i = 0; $i < $goods['number']; $i++) { $redis->lPush($this->goods_number_key, 1); //新增商品库存数量 } } $resetRedis = $redis->lLen($this->goods_number_key); //获取商品库存数量 if (!$resetRedis) { $this->error("系统繁忙,请稍后抢购!"); } return view(); } /** * 用户点击抢购后的操作 * @access public * @author bieanju */ public function goods_number_queue() { $this->judgment_goods(); /* redis 队列 */ $redis = $this->connectRedis(); /* 进入队列 */ $goods_number_key = $redis->lLen($this->goods_number_key); //获取商品库存数量 if (!$goods_number_key) { die('商品库存不足'); } $redis->lPush($this->user_queue_key, $this->user_id); $user_id = $redis->lPop($this->user_queue_key); //移除并且获取列队中用户ID //创建订单,并且减少库存 $data = [ 'user_id' => $user_id, 'goods_id' => $this->goods_id, 'number' => 1, 'create_time' => time(), 'type' => 1,//未支付 ]; $result = Db::name('orders')->insert($data); if (!$result) { die('操作失败'); } $redis->lPop($this->goods_number_key);//减少库存 $this->success('抢购成功'); } /** * 可用定时器, 定时执行该方法, 判断订单是否过期 * 抢购中,超时未支付订单处理办法 */ public function order_no_pay() { //更改订单状态为已取消 $this->judgment_goods(); /* redis 队列 */ $redis = $this->connectRedis(); //恢复库存 $redis->lPush($this->goods_number_key, 1); } /* * 注意 , 下单后指定时间取消订单会出现一个问题, * 如15分钟未支付则将订单改为已取消, 用户在 14分59秒时候发起支付, 支付成功后, 该订单会取消(此时需要做退款处理,或者人工更改订单状态处理) */ } ~~~ ```