2020-09-01 | System Design 中文
电商下单一致性:库存、订单与购物车的事务边界
bibi45
将商城项目笔记中的超卖处理与订单写入流程整理为可验证的一致性方案。
This article is currently available in Chinese. The language switch changes the site interface; the original text is shown below.
下单不是“创建订单后扣库存”的两件独立小事,而是一项需要失败即整体回滚的业务事务。至少要保证:库存不为负、订单商品与订单总额一致、同一请求不会重复扣库存、购物车只在订单成功后清理。
先选择并发策略
悲观锁适合冲突很高且事务很短的场景,例如使用 select_for_update() 锁住将被修改的行;它必须在数据库事务中执行,并注意锁顺序与超时。
更常见的库存扣减方式是单条条件更新:只有库存充足时才更新,因此检查和扣减在同一条 SQL 中完成。
from django.db.models import F
updated = SKU.objects.filter(
pk=sku_id,
stock__gte=quantity,
).update(
stock=F("stock") - quantity,
sales=F("sales") + quantity,
)
if updated != 1:
raise InsufficientStock()
一个下单事务应包含什么
- 验证请求、收货信息、商品状态与数量。
- 用幂等键识别重复提交。
- 在一个事务内创建订单头、逐项原子扣减库存、写订单行并计算金额。
- 事务成功后再清理已结算购物车项、发送消息或触发后续支付流程。
支付回调也必须验证签名、金额、订单状态与幂等性;它不是“收到成功页面跳转”就可以信任。旧笔记中的乐观锁思路是有价值的,但原示例缺少 stock__gte=quantity 条件、事务范围和重复提交处理,因此不能直接用于生产。