订单支付后库存不扣减,如何用RabbitMQ来优化?
上周在Review学员代码的时候,我们发现了一个很基础但很重要的问题:支付回调流程中缺少了库存扣减环节。这类问题虽然基础,但如果直接进入生产环境,可能导致库存的数据和实际销售的情况不一致,出现超卖的情况。能够及时发现这种问题,这就是Review代码的重要性。
先看这段有问题的代码:
go
// 原来的支付回调逻辑(问题代码) func PaymentCallback(ctx context.Context, orderID uint32) error { // 只更新订单状态为已支付 _, err := dao.OrderInfo.Ctx(ctx).Where("id=?", orderID). Data(g.Map{"status": consts.OrderStatusPaid}).Update() if err != nil { return err } // 缺少库存扣减逻辑!商品库存还是原样 return nil }这个问题的核心在于流程设计的不完整,用户支付成功后只是更新了订单状态,却没有同步调整商品库存,可能导致其他用户购买时看到的库存数据不正确。
想要解决这个问题,需要补充缺失的逻辑,更要考虑分布式系统下的流程合理性,这里我们选择引入RabbitMQ实现事件驱动架构,既能解决当前问题,也能方便后续的业务扩展。
问题分析
业务逻辑理解不正确
原逻辑对订单流程的理解是"创建订单→支付成功→完成交易",但正确的流程应该要包含库存相关的环节:
体验AI代码助手
创建订单→预扣库存→支付成功→确认交易→后续处理不同服务之间的协作
在微服务架构中:
- 订单服务负责订单状态流转
- 商品服务负责库存数据维护
两个服务需要通过规范的协作机制保证数据一致性,而不是简单的同步调用。
解决方案
我们重新设计了包含库存管理的订单流程,通过RabbitMQ实现服务间的解耦通信:
创建订单时预扣库存
将库存扣减提前到订单创建的阶段,通过数据库事务保证操作的原子性:
go
// app/goods/internal/logic/goods_info/goods_info.go func ReduceStock(ctx context.Context, req *rabbitmq.OrderCreatedEvent) error { // 使用数据库事务确保原子性 err := g.DB(