WEBKT

基于Pulsar构建高并发最终一致性订单支付系统:实践与思考

26 0 0 0

在高并发电商场景中,构建一个既能保证数据最终一致性,又能兼顾高性能和高可用的订单支付系统,是一个常见的技术挑战。传统的分布式事务解决方案(如XA)在性能和可用性方面往往不尽如人意。事件驱动架构结合消息队列的最终一致性模型,成为了更优的选择。本文将详细探讨如何基于Apache Pulsar,尤其是其事务API和消费者组特性,来设计并实现一个具备最终一致性的订单支付系统。

1. 系统架构概览

我们的支付系统将采用微服务架构,核心服务包括:

  • 订单服务 (Order Service): 负责订单的创建、查询、状态更新。
  • 库存服务 (Inventory Service): 负责商品的库存管理,包括预扣和最终扣减。
  • 支付服务 (Payment Service): 负责与第三方支付网关交互,处理支付请求和回调。
  • 支付网关编排服务 (Payment Gateway Orchestrator): 作为中间层,协调支付流程,确保业务逻辑的正确性。

Apache Pulsar作为核心消息中间件,负责各服务间的事件通知和数据同步。

graph TD
    A[用户下单] --> B{订单服务}
    B -- "OrderCreated事件" --> C(Pulsar Topic: order-events)
    C --> D{库存服务}
    D -- "InventoryPreDeducted事件" --> C
    C --> E{支付网关编排服务}
    E -- "PaymentInitiated事件" --> C
    E -- "发起第三方支付" --> F[第三方支付网关]
    F -- "支付回调" --> G{支付服务}
    G -- "PaymentSuccess/Failed事件" --> C
    C --> B
    C --> D
    C --> H{其他服务}

2. 核心事件流程与Pulsar应用

我们以用户从下单到支付成功的完整事件流为例,说明Pulsar在其中扮演的角色。

2.1 用户下单与订单创建

  1. 用户操作: 用户在前端提交订单。
  2. 订单服务处理:
    • 订单服务接收到请求,进行业务校验(如商品是否存在、用户额度等)。

    • 在本地数据库中创建一笔待支付状态的订单记录。

    • Pulsar 应用: 订单服务使用 Pulsar 事务生产者 (Transactional Producer) 开启一个事务。

      • 在事务内发送一条 OrderCreated 事件到 order-events Topic。该事件包含订单ID、商品信息、用户ID等。
      • 提交Pulsar事务。
    • 如果数据库操作或Pulsar事务提交失败,则回滚,订单创建失败。

    • Pulsar 事务API说明: PulsarClient.newTransaction() 创建事务句柄,transaction.send() 发送消息,transaction.commit() 提交事务。这确保了订单数据在数据库的持久化与 OrderCreated 事件的发布是一个原子操作,实现了本地事务与消息队列的两阶段提交简化版。

2.2 库存预扣减

  1. 库存服务处理:
    • 库存服务订阅 order-events Topic,使用Pulsar消费者组 (Consumer Group) 模式消费 OrderCreated 事件。

    • 收到 OrderCreated 事件后,库存服务尝试对订单中的商品进行库存预扣减(锁定库存)。

    • Pulsar 应用: 库存服务同样使用 Pulsar 事务生产者 开启一个新事务。

      • 如果预扣减成功,发送 InventoryPreDeducted 事件到 order-events Topic。
      • 如果预扣减失败(库存不足),发送 InventoryPreDeductionFailed 事件。
      • 在事务内,确认(consumer.acknowledge()OrderCreated 事件。
      • 提交Pulsar事务。
    • 幂等性处理: 库存服务消费消息时必须是幂等的。如果重复收到 OrderCreated 事件,需要通过订单ID等唯一标识判断是否已处理过,避免重复预扣。

    • 消费者组说明: 多个库存服务实例组成一个消费者组,共同消费 order-events Topic。Pulsar会确保同一分区内的消息只被组内一个消费者消费,保证消息的有序性和负载均衡。当一个实例发生故障时,Pulsar会自动将分区分配给其他可用实例。

2.3 发起第三方支付

  1. 支付网关编排服务处理:
    • 支付网关编排服务订阅 order-events Topic,消费 InventoryPreDeducted 事件。
    • 收到事件后,组装支付请求参数,调用第三方支付网关发起支付。
    • Pulsar 应用: 开启一个事务。
      • 发送 PaymentInitiated 事件到 order-events Topic(可选,用于跟踪支付发起状态)。
      • 在事务内,确认 InventoryPreDeducted 事件。
      • 提交Pulsar事务。
    • 将第三方支付的支付页面或支付链接返回给用户。

2.4 支付结果回调与订单状态更新

  1. 第三方支付回调:

    • 用户完成支付后,第三方支付网关会异步通知支付服务支付结果。
  2. 支付服务处理:

    • 支付服务接收到回调,进行签名验证、状态判断等。
    • Pulsar 应用: 开启一个事务。
      • 如果支付成功,发送 PaymentSuccess 事件到 order-events Topic。事件包含订单ID、支付金额、支付时间、第三方支付交易号等关键信息。
      • 如果支付失败,发送 PaymentFailed 事件。
      • 提交Pulsar事务。
  3. 订单服务处理 (消费 PaymentSuccess/PaymentFailed):

    • 订单服务订阅 order-events Topic,消费 PaymentSuccessPaymentFailed 事件。
    • 收到 PaymentSuccess 事件,将订单状态更新为已支付
    • 收到 PaymentFailed 事件,将订单状态更新为支付失败已取消
    • 幂等性处理: 基于订单ID和事件ID,避免重复更新。
  4. 库存服务处理 (消费 PaymentSuccess/PaymentFailed):

    • 库存服务订阅 order-events Topic,消费 PaymentSuccessPaymentFailed 事件。
    • 收到 PaymentSuccess 事件,将之前预扣的库存进行最终扣减
    • 收到 PaymentFailed 事件,回滚之前预扣的库存,释放库存。
    • 幂等性处理: 基于订单ID和事件ID,避免重复操作。

3. 异常处理与补偿机制

在分布式系统中,网络延迟、服务崩溃、消息丢失/重复等问题是常态。我们需要健壮的异常处理和补偿机制来确保最终一致性。

3.1 幂等性

所有消费事件的服务都必须实现幂等性。通过在事件中携带唯一标识(如订单ID、事件ID),消费者在处理前先查询本地状态,判断是否已处理过该事件,避免重复操作带来的副作用。

3.2 重试与死信队列 (DLQ)

  • Pulsar消费者重试: 当消费者处理消息失败时(如业务逻辑异常、下游服务不可用),可以配置Pulsar的重试机制。消息会被重新投递,带有延迟,等待服务恢复。
  • 死信队列 (Dead Letter Queue): 如果消息经过多次重试仍然失败,Pulsar会将其发送到配置的死信队列Topic。专门的死信队列消费者可以收集这些消息,进行人工干预、错误分析或触发告警。这可以防止异常消息阻塞主业务流程。

3.3 补偿事务

最终一致性意味着在某个时间点数据可能是不一致的,但系统会通过后续操作达到一致。补偿事务是实现这一目标的关键。

  • 场景: 订单已成功预扣库存,但支付失败。此时需要回滚库存。
  • 实现:PaymentFailed 事件被消费后,库存服务通过消费该事件触发库存回滚操作。这是一个补偿性质的事务,它撤销了之前成功的库存预扣操作。
  • 补偿链: 复杂的业务流可能需要一系列的补偿操作。例如,如果订单已创建并扣减了积分,但最终订单取消,就需要补偿回退积分。

3.4 对账系统

支付系统特别需要对账系统来保证财务数据的一致性。

  • 内部对账: 定期比对订单服务、支付服务和库存服务的数据,确保各服务对同一订单的状态认知一致。
  • 外部对账: 定期与第三方支付网关进行对账,核对交易流水,发现差异并进行人工或自动处理。对账系统通常通过批量拉取数据、比对后发出修正指令来工作。

4. 总结

基于Apache Pulsar构建高并发订单支付系统,利用其事务API可以优雅地解决分布式事务中的原子性问题,将本地数据库操作与消息发送捆绑,保证数据不丢失、不重复。消费者组则提供了高可用和负载均衡的能力。结合幂等性、重试机制、死信队列、补偿事务和对账系统,我们可以构建一个强健、可靠,并最终保证数据一致性的支付平台,从容应对高并发场景的挑战。

码匠老王 Pulsar分布式事务最终一致性

评论点评