redis解决“高并发定时秒杀”库存误差问题

前言:高并发的秒杀活动中,通过查询数据库判断是否还有库存,然后对库存字段进行增减,极易出现库存超出或者库存为负的情况,一般来说有3中解决办法(数据库表加锁,memche缓存,redis队列);

我们这里使用redis来解决问题:

1、思路:

  1)触发开始开团的同时,把库存数量更新到id对应的队列上去(定时更新,或者手动更新)

  2)用户请求接口,如果队列长度>0,移除一个队列记录,同时对数据库进行相应操作

  3)如果队列长度<=0,拦截用户的访问,返回‘无库存’

 步骤:

1、后台准点插入记录到redis

$redis = get_redis(); 
// 1、数据库获取拼团信息
$sql = "select id,title,surplus_num,high_lines,ku_1,ku_2,ku_3,ku_4 from group_goods";
$arr = getrecord_array($sql);

//2、删除旧redis队列
foreach ($arr as $key => $value) {
    //商品id
    $goods_id = $arr[$key]['id'];
    $redis->delete('acst_goods_high_lines'.$goods_id);
}
// 3、准点插入记录到redis foreach ($arr as $key => $value) { //商品id $goods_id = $arr[$key]['id']; //库存数量 $num = $arr[$key]['ku_3']; //json转换 $in_list = json_encode($arr[$key]); for ($i=0; $i < $num; $i++) { $redis->lpush('acst_goods_high_lines'.$goods_id,$in_list); } }

2、客户端抢购

$redis = get_redis(); 
//获取队列长度
$leng = $redis->lLen('acst_goods_high_lines'.$goods_id);
if($leng>0){
   //移除一条记录
$redis->lpop('acst_goods_high_lines'.$goods_id); //减去库存---增加成功开团数 $sql = "update group_goods set surplus_num = surplus_num-1,mtime = $t,success_num=success_num+20 where id = $goods_id limit 1"; exec_db($sql); }else{ echojson('已售罄,敬请期待',0); }

 

posted @ 2018-06-09 15:46  x-duck  阅读(442)  评论(0编辑  收藏  举报