网站首页 文章专栏 利用redis实现 限时秒杀
常规做法:
//连接数据库或缓存,查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数,因为有可能在剩余一件时,同时过来两个请求。
建议做法:
基于单线程处理思想。一个个验证,即使有很多用户同时发送请求,也是一个个检查并给与抢购资格,一旦库存抢尽,后面的用户就无法继续了。之后我们再引导这些用户去完成订单的其他步骤,到这里才涉及到与数据库的交互。
建立秒杀商品时,立即建立对应的缓存仓库
public function setredis(){ $limit=20; //上限总数 $goods_id=1001; //商品ID $finish_time='2019-10-8 00:00:00'; //活动结束时间 $reids_expire=strtotime($finish_time)-time(); $reids_key='goods_limits_'.$goods_id; $len=$this->redis->llen($reids_key); //获取上次活动剩余的库存 一般为0 $num=$limit-$len;// 这次需要追加的数量 for ($i=1;$i<=$num;$i++){ $this->redis->lpush($reids_key,$i); //生成一个总库存列表 } if($this->redis->llen($reids_key)==$limit){ $this->redis->expire($reids_key,$reids_expire+3600); //习惯给过期时间多设置比时间长一点 return true; } return false; }
2.用户发起请求,验证
public function check($goods_id){ $reids_key='goods_limits_'.$goods_id; $uid=session('uid'); $last_time=$this->redis->ttl($reids_key); if(!$last_time){ return ['msg'=>'已过期','status'=>-200]; } $check=$this->redis->lpop($reids_key); if(!$check){ return ['msg'=>'该商品已被抢完','status'=>-200]; } $goods_snag_key='goods_snag_'.$goods_id.'_'.$uid; $this->redis->INCR($goods_snag_key,$last_time+3600); //用户购买这件商品数量,用于判断 限制用户购买数量,无需要,可省略 return ['msg'=>'抢到了,请继续后续处理','status'=>200]; }
转载请注明出处