标准答案
- 数据库可用 `stock > 0` 的条件更新原子扣减,并通过订单或扣减记录保存成功证据。
- 缓存预扣适合快速拦截明显超量请求,但要处理缓存与数据库不一致、回滚和重启恢复。
- 队列把突发请求排队,消费端按 SKU 或商品分片处理,设置过期、取消和失败补偿。
- 库存、订单、支付和发货要定期对账,发现预扣未落库或订单未扣库存时执行受控修复。
题目解析
库存的权威事实必须落在能事务性记录订单、扣减和状态的存储中。缓存预扣可以减少明显无效请求,但缓存丢失、回滚和并发重试都可能让它与数据库短暂不一致。
队列只改变处理时机,不会自动消除重复消息。消费端要用订单或请求幂等键、条件更新和扣减记录保证同一业务请求最多产生一次有效扣减。
取消、超时未支付、支付失败和库存回滚都要进入状态机,并通过定期对账发现预扣未落库、订单无库存或库存异常减少。修复动作必须可追踪,不能直接改一个缓存数字。
常见误区
- 误区:只在 Redis 扣减库存而不落库。改正:Redis 只能做快速拦截,权威库存和订单结果必须由数据库或明确的事实存储确认。
- 误区:队列重复消费会自动被系统消除。改正:使用幂等键、唯一约束和影响行数判断,重复消息不能再次扣减。
- 误区:只处理支付成功路径。改正:设计取消、超时未支付、支付失败和预扣回滚,并用对账发现漏处理。