|

Aimee

Write the Code. Change the World.

接到秒杀需求,你先别急着写代码

· 分享镜

接到秒杀需求,你先别急着写代码

秒杀场景有一个核心矛盾:用户点击抢购的瞬间,并发请求可能几百上千个同时到达,但库存就那么几件。

在写任何一行代码之前,得先想清楚一件事:库存扣减,放在哪一步?

这个问题没有"显然正确"的答案,下单时扣和付款时扣都有问题。

两种方案,都有问题

方案 A:下单时扣库存。

用户点"立即购买",库存 -1,订单生成,再去付款。

听起来顺,但有个场景:用户下了单不付款,库存一直被占着。100 件商品,100 个人下单全不付款,真正想买的人进来看到"已售罄"。

结果是:商品没卖出去,库存却没了。

方案 B:付款时扣库存。

用户先下单,付款成功后再扣库存。

这个问题更严重:1000 个人同时下单,库存还有 100,订单全部生成了。最后付款成功的有 300 人,超卖了 200 件。

方案A:下单时扣库存方案B:付款时扣库存
问题不付款也占库存,真实用户买不到订单超量生成,付款后超卖
适用低并发、商品充足不推荐

实际项目怎么做

没有完美方案,只有合适的取舍。主流做法是分三层:

第一层:下单时用 Redis 预占库存。

不是真扣,是"锁住"。Redis 原子操作先减,成功才允许下单。这一步必须用 Redis 而不是数据库——并发量一上来,数据库行锁撑不住。

// 原子操作,库存不够直接返回失败
Long remaining = redis.decrement("stock:activity:100");
if (remaining < 0) {
    redis.increment("stock:activity:100"); // 回补
    return "库存不足";
}
// 预占成功,生成订单

第二层:超时释放预占库存。

下单后 15 分钟没付款,预占的库存自动释放,别人可以买。用延迟队列或 Redis 过期监听实现。

第三层:付款成功后写数据库真实库存。

付款成功后,同步扣减 DB 里的实际库存,做最终确认。

流程示意图

这道题没有完美解

秒杀库存的核心矛盾是:扣早了怕占而不买,扣晚了怕超卖。预占 + 超时释放是折中,不是完美解,但是够用的解。

Redis 预占解决并发超卖,超时释放解决恶意占库存,DB 最终确认保证数据准确。三步缺一不可。

评论0

登录后参与评论。

还没有评论,来抢沙发吧。

回到顶部