php + redis实现秒杀系统
//添加商品库存 public function addGoodsStock(Request $request) { $goods_id = $request->input('goods_id'); $store = $request->input('store'); //设置商品库存的key $key = 'seckill_goods_id_'.$goods_id; $res = Redis::set($key,$store); return $res; }
//用户秒杀商品 public function buy(Request $request) { $uid = $request->input('uid'); $goods_id = $request->input('goods_id'); //商品库存key $key = 'seckill_goods_id_'.$goods_id; //监听对应的key,事务提交之前,如果key被修改,则事务被打断 Redis::watch($key); //获取商品库存 $store = Redis::get($key); //抢购成功用户集合key $setKey = 'userGoodsSuccess'; //判断该用户是否已经抢购过 //该用户id是否在抢购用户集合中 $userBuyStatus = Redis::sismember($setKey,$uid); if($userBuyStatus){ return '您已抢过!'; } if($store){ //记录用户信息,更新库存 //保证这一组命令,要么全部成功,要么都不成功 Redis::multi();//开始事务 Redis::decr($key);//减少库存 //将用户id添加到抢购成功用户集合中 Redis::sadd($setKey,$uid); $result = Redis::exec();//提交,判断当前的key是否被某个客户端修改了 if($result){ //操作数据库,修改商品库存销量 DB::table('goods')->where('id', $goods_id)->decrement('stock', 1, ['sale' => DB::raw('`sale`+1')]); //创建订单信息 return '抢购成功!'; }else{ return '抢购失败,请重试!'; } }else{ return '已抢光!'; } }
/** * redis队列 * 初始化库存队列 * @param Request $request * @return string */ public function init(Request $request) { // 商品库存 $goods_id = $request->input('goods_id'); $store = $request->input('store'); $key = 'list_seckill_goods_id_'.$goods_id; //防止对已经设置过的商品库存进行覆盖 if(!empty(Redis::llen($key))) { return '已经设置了库存'; } // 初始化缓存,删除抢购用户id队列key和成功信息保存key,这个是抢购时生成的,防止错乱,初始化删除 $userListKey = 'user_goods_id_'.$goods_id; Redis::command('del', [$userListKey, 'success']); // 将商品存入Redis链表中 for($i = 1; $i <= $store; $i++) { Redis::lpush($key, $i); } // 设置过期时间// Redis::expire($key, 120); echo '商品存入队列成功,数量:'.Redis::llen($key); }
/** * redis队列 * 抢购 * @param Request $request * @return string */ public function start(Request $request) { // 模拟随机登录用户 $uid = mt_rand(1, 9999);// $uid = $request->input('uid'); $goods_id = $request->input('goods_id'); $key = 'list_seckill_goods_id_'.$goods_id; // 从链表的头部删除一个元素,返回删除的元素,因为pop操作是原子性,即使很多用户同时到达,也是依次执行 $count = Redis::lpop($key); if (!$count) { return '已抢光!'; } //已抢购用户id队列 $userListKey = 'user_goods_id_'.$goods_id; //判断该用户是否已经抢购过 //该用户id是否在抢购用户集合中 $userBuyStatus = Redis::sismember($userListKey,$uid); if($userBuyStatus){ return '您已抢过!'; } //将用户id添加到抢购成功用户集合中 Redis::sadd($userListKey,$uid); $msg = '抢到的人为:'.$uid.',抢到商品的顺序为第'.$count.'个'; Redis::lpush('success', $msg); //操作数据库,修改商品库存销量 DB::table('goods')->where('id', $goods_id)->decrement('stock', 1, ['sale' => DB::raw('`sale`+1')]); //创建订单信息 return '恭喜您抢购成功!'; }
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。