秒杀抢购时的超卖处理

类似商城的秒杀场景,大家肯定都遇到过。如何处理好秒杀时候商品的库存限制问题,真的一直让人头大。

常见的处理方案不外乎下面两种:

1、锁

表锁、行锁、文件锁。将需要操作的商品数据锁定,当前用户购买成功后,释放锁,允许其他用户操作该条数据。

2、队列

将请求放入队列中,也就是所有的请求都进行排队等待,按照顺序依次处理。并发请求都放到队列中,由额外进程串行处理,并发问题就不存在了,但是要额外进程支持以及处理延迟严重。

以上两种方案都避免不了“等待”的问题,高并发极端场景下,很可能会造成系统响应异常。暂时不对这两种方案作详解。

最近在学习 redis,发现可以结合 redis 的事物和 watch 命令巧妙解决超卖的问题。

老规矩,使用 watch 之前先来了解下它的特性。毕竟使用场景是以事物的特性为基础的。

watch 命令可以监控一个或多个键,一旦其中一个键被修改或删除,之后的事物就不会执行。监控一直持续到 exec 命令。

话不多说,直接上代码。

$redis = JRedis::getInstance();
$key = 'saleCount:id:3';

$redis->watch($key);
//销量
$sales = $redis->get($key);
//库存
$qty = 8;
if ($sales >= $qty) {
    exit("已售罄");
}
//开启事务
$redis->multi();
$redis->incrby($key, 1);
$result = $redis->exec();
if ($result) {
    //执行数据库的销量增加操作,执行订单创建等操作
    exit("校验成功,开始数据库操作");
} else {
    $redis->incrby($key, -1);
    exit("重新下单");
}

亲测效果杠杠的,而且就效率来说,要优于锁和队列。而且,还可以使用 redis 分摊数据库的压力,岂不是美滋滋。

5分推荐。

 

好文章分享:

https://zhuanlan.zhihu.com/p/269746986

https://zhuanlan.zhihu.com/p/336113193

 

posted @ 2020-12-13 16:21  所见即我  阅读(468)  评论(0编辑  收藏  举报