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);
}
    原文作者:x-duck
    原文地址: https://blog.csdn.net/qq_40854036/article/details/80664543
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞