商品库存扣减方案
文章目录
- 1. Lua脚本 + Redis(业界首选,综合最优)
- 2. Redis原子命令(DECRBY + 结果校验)
- 3. Redis事务(MULTI/EXEC)
- 4. 分布式锁(基于Redis实现)
- 5. Redisson客户端封装(Java生态首选)
- 6. 数据库事务 + Redis双写
- 业界主流:
1. Lua脚本 + Redis(业界首选,综合最优)
核心逻辑:将“检查库存→扣减库存→返回结果”的完整逻辑用Lua脚本编写,通过Redis的 EVAL
命令执行,利用Redis对Lua脚本的原子性支持(整个脚本作为单个命令执行,不被其他请求打断)。
优势:
- 原子性最强:天然避免并发冲突,从根本上解决超卖问题;
- 灵活性高:支持复杂逻辑(如库存阈值校验、阶梯扣减、关联优惠券判断等);
- 性能最优:一次网络请求完成所有操作,减少IO开销;
- 兼容性好:不依赖特定语言或客户端,所有Redis客户端都支持。
适用场景:几乎所有库存扣减场景,尤其是高并发秒杀、促销活动(如淘宝双11、京东618的核心库存逻辑)。
业界案例:阿里云秒杀系统、京东商品库存核心模块、微信支付库存校验。
2. Redis原子命令(DECRBY + 结果校验)
核心逻辑:直接使用Redis的 DECRBY
命令扣减库存,通过返回结果判断是否成功(若结果≥0则成功,否则回滚)。
优势:实现最简单,单命令性能极致,适合超高并发场景;
缺点:逻辑逆向(先扣减再判断),可能出现短暂负库存(需立即回滚),不支持扣减前的复杂校验。
适用场景:超高并发且逻辑极简的场景(如秒杀活动的第一道库存拦截)。
业界案例:部分秒杀系统的前置过滤层、简单商品的快速库存扣减。
3. Redis事务(MULTI/EXEC)
核心逻辑:通过 MULTI
标记事务,将“查库存→扣库存”命令放入队列,EXEC
一次性执行。
优势:原生支持,无需额外依赖,适合中小并发场景;
缺点:需在客户端二次判断库存(乐观锁机制),不支持复杂逻辑,执行失败时需手动回滚。
适用场景:并发量不高、逻辑简单的普通商品下单(如日均订单量10万级以下的电商)。
4. 分布式锁(基于Redis实现)
核心逻辑:用 SET key value NX PX
获取分布式锁,确保同一时间只有一个线程操作库存,执行“查库存→扣库存”后释放锁。
优势:支持复杂业务逻辑(如结合用户权限、订单状态校验);
缺点:实现复杂(需处理锁超时、重入、误释放等问题),性能损耗较高(加锁/释放锁开销)。
适用场景:需要结合复杂业务规则的库存扣减(如VIP用户优先扣减、关联订单状态的库存调整)。
业界案例:部分电商的订单确认环节(需关联物流、优惠券等多维度校验)。
5. Redisson客户端封装(Java生态首选)
核心逻辑:通过Redisson提供的 RSemaphore
(信号量)或 RLock
(分布式锁),底层自动实现原子性操作(内部基于Lua脚本或Redis命令)。
优势:封装完善,简化分布式锁、原子操作的开发(如自动续期、重入锁);
缺点:仅限Java生态,灵活性略低(依赖客户端实现)。
适用场景:Java技术栈项目,希望减少手动处理分布式问题的场景。
6. 数据库事务 + Redis双写
核心逻辑:以MySQL等数据库为权威数据源,通过数据库事务保证库存扣减原子性,同步更新Redis缓存(最终一致性)。
优势:强一致性(数据库事务保证),适合对数据可靠性要求极高的场景;
缺点:性能差(数据库成为瓶颈),Redis与数据库可能存在短暂不一致。
适用场景:并发量低、高价值商品(如奢侈品、珠宝)的库存管理。
业界主流:
- 绝对主流:Lua+Redis 是高并发库存扣减的事实标准,几乎所有大型电商、秒杀系统的核心库存逻辑都采用此方案(兼顾原子性、性能、灵活性)。
- 补充方案:原子命令(DECRBY)用于极致性能场景,分布式锁用于复杂业务场景,数据库事务仅用于低并发、高价值商品场景。
简单说:Lua+Redis = 库存扣减的“最优解”,是业界处理高并发库存问题的首选技术方案。