2. Saga执行流程:Choreography与Orchestration两种编排模式详解

Saga事务的核心在于将一个长事务拆分为多个本地事务(Local Transaction),并通过补偿操作(Compensation)来保证全局一致性。根据决策与协调逻辑的分布方式,Saga分为两种经典编排模式:Choreography(编排/舞蹈模式)与Orchestration(编排/编舞模式)。理解两者的执行流程、优缺点及适用场景,是构建可靠分布式事务的基础。

2.1 Choreography(编排模式)

在Choreography模式中,每个参与微服务在完成本地事务后,通过事件(Event)通知下一个服务执行。没有中央协调器,所有服务通过消息队列(如Kafka、RabbitMQ)进行异步通信,形成一条事件驱动的执行链。

核心特征:去中心化、事件驱动、服务间点对点通信。

执行流程步骤

  1. 订单服务创建订单(状态:待支付),发布“订单已创建”事件。
  2. 支付服务消费事件,执行扣款操作,发布“支付成功”事件。
  3. 库存服务消费事件,执行扣减库存操作,发布“库存已扣减”事件。
  4. 物流服务消费事件,创建物流单,发布“物流已创建”事件。
  5. 若任意步骤失败(如支付超时),该服务发布“支付失败”事件,上游服务监听后触发补偿操作(如取消订单、释放库存)。
Choreography 模式执行流程 订单服务 支付服务 库存服务 物流服务 订单已创建 支付成功 库存已扣减 补偿:取消订单 事件总线(Kafka / RabbitMQ) 发布/订阅 发布/订阅 发布/订阅 发布/订阅
适用场景:业务流程简单、服务数量少(通常不超过5个)、团队对事件模型有成熟治理经验。典型例子:电商下单流程(订单→支付→库存→物流)。

2.2 Orchestration(编舞模式)

Orchestration模式引入一个中央协调器(Orchestrator),负责管理整个Saga的执行状态。协调器通过命令(Command)驱动各参与服务执行本地事务,并监听响应结果。若某步骤失败,协调器根据预定义的补偿流程反向调用补偿操作。

核心特征:中心化、命令驱动、状态由协调器统一管理。

执行流程步骤

  1. 协调器收到“创建订单”请求,向订单服务发送“创建订单”命令。
  2. 订单服务执行成功,返回“订单已创建”响应。
  3. 协调器记录状态,向支付服务发送“扣款”命令。
  4. 支付服务执行成功,返回“支付成功”响应。
  5. 协调器继续向库存服务发送“扣减库存”命令,以此类推。
  6. 若支付失败,协调器向订单服务发送“取消订单”补偿命令。
Orchestration 模式执行流程 Saga 协调器 状态机 + 补偿路由 订单服务 支付服务 库存服务 物流服务 创建订单 扣款 扣库存 创建物流 订单已创建 支付成功 库存已扣减 物流已创建 补偿:取消订单 Saga 状态存储(DB / Redis)
适用场景:业务流程复杂、服务数量多(5个以上)、需要严格的状态追踪与审计、团队希望集中管控补偿逻辑。典型例子:跨行转账、订单+支付+库存+积分+通知的复杂流程。

2.3 两种模式对比

对比维度 Choreography(编排) Orchestration(编舞)
协调方式 事件驱动,无中心节点 命令驱动,中央协调器
通信模式 异步事件(发布/订阅) 同步/异步命令(请求/响应)
状态管理 分散在各服务的事件日志中 集中存储在协调器
补偿逻辑 各服务自行监听失败事件并补偿 协调器统一触发补偿命令
耦合度 服务间通过事件耦合,需理解上下游业务 服务仅与协调器交互,解耦程度高
可观测性 追踪困难,需跨服务关联事件链 协调器提供单一视图,易于追踪
复杂度 服务数量少时简单,多时易混乱 协调器可能成为瓶颈,但流程清晰
典型实现 Eventuate Tram、Axon Framework Camel、Temporal、Camunda

2.4 可观测性视角下的关键差异

从OpenTelemetry追踪的角度,两种模式对Span的生成与关联方式有本质区别:

  • Choreography:每个服务独立生成Span,需要通过Propagation(传播)机制将TraceId通过消息头传递。由于事件是异步的,需要额外处理消息链路关联(如Kafka Consumer Span与Producer Span的父子关系)。
  • Orchestration:协调器作为根Span(Root Span)的持有者,每次命令调用生成子Span。整个Saga的Trace结构呈树状,根节点为协调器,子节点为各服务。失败补偿时,补偿Span作为根Span的兄弟或子Span,结构清晰。
实践注意:在Choreography模式中,若事件总线出现积压或消费失败,Span的结束时间可能严重滞后于实际业务完成时间,导致Trace时间线失真。建议在消息消费端显式注入span.end()时机,而非依赖自动检测。

2.5 选择建议

没有绝对优劣,选择取决于业务场景与团队能力:

  • 优先选择Choreography:团队熟悉事件驱动架构、服务数量≤5、业务流程线性、对追踪要求不高。
  • 优先选择Orchestration:需要严格的事务保证、服务数量多、业务流程有分支/循环/并行、需要集中式可观测性仪表盘。
  • 混合模式:大型系统中,可对核心链路使用Orchestration,对边缘子流程使用Choreography,但需注意TraceId的统一传递策略。