2026直播带货小程序的高并发库存设计:超卖防护、商品快照与支付回调的工程实践
(平台提示:本文可能是商业推广软文)
2026年,一场中腰部主播的直播,讲解链接弹出来的那几秒钟,后端要顶住平时几十倍的瞬时请求。普通电商的库存系统在这种脉冲流量下几乎必出问题:要么超卖、要么按错价格付款、要么支付回调丢单。这篇不聊选品和话术,只讲后端三件事——直播间库存怎么防超卖、下单时为什么要存商品快照、支付回调怎么做幂等和关单回滚。
一、直播间库存和普通电商的区别在哪
普通商城的下单流量是平的,一天几千单分摊在十几个小时里。直播间不是,一场两小时的直播,真正出单集中在主播讲到某个品的那三五分钟,QPS 可能瞬间冲到平时的几十倍。这带来三个不一样的工程要求。
库存扣减必须在内存层做。直接打数据库行锁,几千个并发请求能把连接池打满。主播会在讲解过程中切品、改专享价、调库存,下单那一刻的价格和库存必须被冻结下来,不能让用户付到一半价格变了。直播订单的关单超时要比普通电商短,用户抢到了不下单,库存占着,后面排队的人买不到,主播节奏全乱。
二、超卖防护:Redis 预扣加数据库最终一致
通行做法是两段式。库存余量放在 Redis,扣减动作在 Redis 里原子完成,扣成功了才去创建订单;订单支付超时或者取消,再把库存加回 Redis。
关键是扣减这一步必须原子。很多团队踩过的坑是先读库存、判断大于零、再写回去,两步之间隔着网络请求,并发下两个请求读到同一个余量,都判断有货,都下单,就超卖了。正确做法是把判断和扣减写进一段 Lua 脚本,Redis 单线程执行,脚本里完成判断余量、扣减、返回结果,外面拿不到中间态。
伪代码大致是这样:
-- stock.lua
local key = KEYS[1]
local qty = tonumber(ARGV[1])
local left = tonumber(redis.call('GET', key) or '0')
if left < qty then
return -1
end
redis.call('DECRBY', key, qty)
return left - qty
应用层拿到返回值大于等于零才继续走下单,返回 -1 直接给前端已抢光。
Redis 和数据库的一致性怎么保证?订单创建成功、支付完成之后,异步把数据库库存表减一次;每天凌晨做一次对账,拿 Redis 余量和数据库已售订单勾稽。不要追求 Redis 和 DB 强一致,那会把性能优势全部吐回去,最终一致加日对账就够直播电商这个量级。
三、商品快照:讲 A 链接不能按 B 商品的价付款
直播间有个特殊动作叫切品。主播上一秒还在讲甲,下一秒切到乙,后台把讲解中的商品标识一切,前端橱窗顺序就变了。如果下单接口实时去读商品表的当前价格和库存版本,用户购物车里那件甲商品,可能在他点支付的时候已经被换成了乙的价格。
工程上的解法是下单时生成一份商品快照。订单表里除了商品 ID,还要冗余三列:下单时的单价、规格快照、库存版本号。支付时直接读订单表里的快照金额,不再回去查商品表。这样即使主播后台把价格改成了直播专享价、把库存清零,已经下单的用户按他下单那一刻的价格付款,不会扯皮。
快照还要带一个商品版本号。主播在讲解中临时改价,商品表版本号加一,下单时如果发现购物车里的商品版本和最新版本对不上,前端弹一个价格已变动请重新确认,而不是默默按旧价扣钱。
四、支付回调:幂等是命门
微信支付、支付宝的支付结果都是异步回调通知业务系统。回调有两个天然问题:会重复、会迟到。
重复是因为支付渠道在规定时间内没收到业务方返回的成功应答,会按策略重推,可能推好几次。迟到是因为用户支付成功那一刻,回调网络抖动,订单在用户那边已经显示支付完成,业务系统却还没收到通知。
回调接口必须做幂等。做法是拿支付回调里的商户订单号做唯一键,接到回调先查这条订单是不是已经处理过:已支付直接返回成功,不重复改状态、不重复发权益。整个更新订单状态、扣减实际库存、发券发短信放在一个数据库事务里,要么一起成功要么回滚,避免状态改了一半。
回调失败要有兜底。不能只靠回调,要加一个主动查单的定时任务:订单创建后若干分钟还没收到回调,主动调支付渠道的查询接口查一次真实支付状态,以渠道返回为准。纯靠被动回调,遇到渠道漏通知就是丢单。
五、关单与库存回滚:抢到不下单怎么办
直播间用户下单后通常给一个很短的支付窗口,比如五到十分钟。超时没付,订单要自动关闭,占着的库存要还回 Redis,让排队的人能抢到。
这里容易踩的坑是关单和回调的竞态:订单刚被定时任务判超时关掉、库存刚加回去,支付回调这时候姗姗来迟说这笔其实付成功了。处理办法是关单动作也要幂等,并且关单前再查一次支付渠道的真实状态——已经付成功的,不能关;确实没付的,才关单回滚库存。回滚库存同样走 Lua 脚本原子加回,不能两个关单任务并发把同一笔库存加两次。
六、几个常被问到的点
问:库存直接放数据库行不行?答:平峰可以,直播脉冲流量下不行,行锁会把连接池堵死。Redis 预扣扛并发,数据库只做最终对账。
问:商品快照会不会让商品表改价不生效?答:只影响已下单未支付的那部分订单,前端会弹价格变动提示,未下单用户看到的还是最新价。
问:支付回调重复了会重复发货吗?答:不会,订单号做唯一键,已支付状态直接返回成功,权益只发一次。
这套结构扛单场几万到几十万观看的直播带货是够用的。量级再往上走,库存 Redis 要按直播间拆 key,关单任务要从单机轮询改成消息队列延迟消息,那是后话。
浙公网安备 33010602011771号