分布式事务鉴权拦截的Saga状态持久化实现方案 - 第2节

Saga 执行流程:正向补偿与逆向回滚

Saga 是一种长活事务(Long-Running Transaction, LRT)模式,它将一个全局事务拆分为多个本地事务(子事务),每个子事务都对应一个正向操作(T₁, T₂, …, Tₙ)和一个补偿操作(C₁, C₂, …, Cₙ)。Saga 的核心执行流程分为两种路径:正向补偿(全部成功)与逆向回滚(部分失败)。

正向补偿流程(Happy Path)

  1. 顺序执行:编排器或协同消息驱动依次调用 T₁, T₂, …, Tₙ。
  2. 本地提交:每个子事务执行完成后立即提交本地数据库,释放锁资源。
  3. 状态持久化:每完成一个子事务,将当前状态(如 COMPENSATING / COMPLETED)写入 Saga 日志表。
  4. 全局完成:所有 Tₙ 执行成功,Saga 标记为 FINISHED,无需调用任何补偿操作。

逆向回滚流程(Compensating Path)

  1. 失败检测:子事务 Tₖ 执行失败(业务异常、超时、网络中断)。
  2. 触发补偿:编排器或协同机制立即启动逆向补偿,按逆序调用 Cₖ₋₁, Cₖ₋₂, …, C₁。
  3. 幂等补偿:每个补偿操作必须幂等,确保重复调用不产生副作用。
  4. 状态标记:补偿完成后,Saga 日志记录 ROLLBACK 状态,全局事务回滚完成。
关键原则:补偿操作必须能够语义上撤销正向操作的效果,而非简单的数据库回滚。例如,正向操作为“扣减库存”,补偿操作应为“增加库存”;正向操作为“发送邮件”,补偿操作可为“发送撤销邮件”或记录已撤销状态。
Saga 正向补偿与逆向回滚流程 Saga 正向补偿与逆向回滚流程 T₁ 执行 T₂ 执行 T₃ 执行 ✓ 全部成功 T₂ 失败 ✗ C₁ 补偿 C₂ 补偿 回滚完成 补偿逆序执行 C₂ → C₁

Saga 编排器(Orchestrator)与协同(Choreography)模式对比

Saga 的两种主流实现模式——编排器(Orchestrator)与协同(Choreography)——在控制流、耦合度、可维护性等方面存在显著差异。选择哪种模式取决于系统规模、团队能力和事务复杂度。

编排器模式(Orchestrator)

  • 核心思想:引入一个中央编排器(Orchestrator)对象,负责协调所有子事务的执行顺序、失败检测和补偿调度。
  • 控制流:编排器通过命令/事件驱动各参与者,参与者只响应编排器的指令,不感知其他参与者。
  • 状态管理:编排器集中维护 Saga 状态,便于持久化和监控。
  • 优点:流程清晰、易于调试、适合复杂事务(如嵌套 Saga、条件分支)。
  • 缺点:编排器成为单点瓶颈,增加系统耦合度。

协同模式(Choreography)

  • 核心思想:没有中央协调者,每个子事务完成后通过事件(Event)触发下一个子事务。
  • 控制流:参与者之间通过消息队列(如 Kafka、RabbitMQ)异步通信,形成事件链。
  • 状态管理:状态分散在各参与者本地,需通过事件溯源或分布式追踪还原全局状态。
  • 优点:去中心化、高可扩展性、适合微服务松耦合场景。
  • 缺点:流程隐式、调试困难、补偿逻辑分散,容易形成“事件风暴”。
对比维度 编排器模式(Orchestrator) 协同模式(Choreography)
控制中心 中央编排器 无中心,事件驱动
耦合度 参与者与编排器耦合 参与者之间松耦合
状态持久化 集中存储在 Saga 日志表 分散在事件存储或本地日志
调试难度 低(流程可见) 高(需追踪事件链)
扩展性 编排器可能成为瓶颈 天然支持水平扩展
适用场景 复杂事务、需要严格顺序控制 简单线性事务、高吞吐场景
典型实现 Axon Framework、Camunda、自研编排器 Eventuate Tram、Kafka Streams、自研事件总线
选型建议:如果团队对事务流程有强管控需求,且愿意接受一定的中心化风险,优先选择编排器模式;如果系统追求极致松耦合和弹性伸缩,且事务链路简单(通常不超过 5 步),协同模式更合适。
编排器模式 vs 协同模式架构对比 编排器模式 vs 协同模式架构对比 编排器模式 编排器 服务 A 服务 B 服务 C 协同模式 服务 A 服务 B 服务 C 事件总线(Kafka / RabbitMQ) 编排器:集中控制,流程显式 适合复杂事务、严格顺序 协同:事件驱动,去中心化 适合简单链路、高扩展性

模式选择决策树

在实际项目中,可以通过以下决策树快速判断采用哪种模式:

  1. 事务步骤是否超过 5 个? → 是 → 编排器模式;否 → 继续判断。
  2. 是否需要动态条件分支或嵌套 Saga? → 是 → 编排器模式;否 → 继续判断。
  3. 团队是否熟悉事件驱动架构? → 是 → 协同模式;否 → 编排器模式。
  4. 系统是否要求极致松耦合和独立部署? → 是 → 协同模式;否 → 编排器模式。
常见陷阱:在协同模式中,如果事件顺序依赖严格的时间戳或全局 ID,容易因网络延迟导致乱序。建议在事件体中携带序列号或前驱事件 ID,并在消费者端做顺序校验。编排器模式则需注意编排器自身的高可用和幂等性设计,避免编排器宕机导致 Saga 状态丢失。