Skip to content

订单支付后库存不扣减,如何用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(