|

Aimee

Write the Code. Change the World.

库存扣减时机这道题,答案不是技术给的

· 分享镜

库存扣减时机这道题,答案不是技术给的

下单时扣库存还是付款时扣库存——这个问题的答案不取决于技术选型,取决于你的商品形态和业务对超卖的容忍度。


三种商品,三种答案

虚拟商品(充值卡、游戏道具、电子书):没有物理库存限制,下单即视为"交付",库存计数纯粹是业务规则。通常选择付款成功后扣减,因为未付款的下单没有任何实际成本,不需要占位。

实物商品、常规并发:下单时预占库存(从可售库存里减掉),设 30 分钟超时释放;付款成功后写实际扣减记录。预占保证了用户在支付过程中商品不会被别人买走,超时释放保证了占而不买的库存最终回来。

高价值低库存商品(限量款、秒杀):专门做 Redis 原子预占,下单前先在缓存层抢位置,抢到再允许进入下单流程。这类场景数据库扛不住并发,缓存层是第一道闸。


超卖的容忍度也是个变量

有些业务允许"超卖后补单":电商平台的日用百货,库存记录不一定实时精确,超卖了联系供应商补货。这类商品在下单阶段不做强校验,付款成功后异步核减,容忍一定程度的超发。

有些业务零容忍:演唱会门票、限量联名款。多发一张就是真实损失,必须在下单瞬间把库存锁住,绝不允许超发。

不是所有商品都要走最严格的方案。把所有商品都做成"秒杀级别的强校验",开发成本高、系统复杂度高,对于日均销量 10 件的长尾商品完全没必要。


预占库存和营销库存是两层

实际业务里库存往往不止一层:

层级含义谁在用
物理库存仓库里实际有多少仓储系统
可售库存减去已预留/已损耗后的可卖数量订单系统
营销库存活动专供,独立于普通售卖促销系统

下单预占的是可售库存,付款后触发仓库备货;营销库存单独管,不和普通库存混用——秒杀商品单独一个 Redis key,抢完了对普通渠道无影响。


预占之后,超时释放的可靠性

超时释放靠延迟队列或定时扫描。延迟队列的问题是:如果 MQ 消费延迟了,库存被额外多锁了一段时间。定时扫描的问题是:扫描周期越短,数据库压力越大。

两种方式的选择取决于库存宝贵程度:门票类用延迟队列(精确释放),普通商品用定时扫描(每 5 分钟跑一次,误差可接受)。

超时释放也要幂等——同一个预占记录可能被重复扫到,用 CAS 更新(WHERE status = OCCUPIED AND expire_time < NOW())保证只释放一次。

评论0

登录后参与评论。

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

回到顶部