Saga 编排与协调
用途:长流程、多服务、含人工环节的业务如何保证最终一致时查阅
定义
「定义」小节链接Saga 把一个跨多个本地事务的业务操作,拆成一串各自可提交、各自有补偿的本地事务:T1, T2, …, Tn;失败时按逆序执行补偿 C1, C2, …, Cn-1。
与 2PC 的本质差别:没有全局事务与协调者持锁,每一步都是真实提交,靠补偿撤销已产生的影响。
两种编排方式
「两种编排方式」小节链接| 方式 | 谁决定下一步 | 特点 | 风险 |
|---|---|---|---|
| 编排式(Choreography) | 各服务监听事件自行推进 | 无中心、易扩展、服务间零直接依赖 | 流程分散难看清,循环依赖与重复消费风险 |
| 协调式(Orchestration) | 中央协调器按状态机驱动 | 流程集中可见、易监控与重试、补偿顺序可控 | 协调器成为关键组件,需高可用与状态持久化 |
经验判断:步骤 ≤3 且无分支时可用编排;步骤多、含条件分支或人工环节时用协调。
补偿的设计要求
「补偿的设计要求」小节链接- 补偿必须语义正确:不是“把数据改回去”,而是“业务上撤销”。已发出的通知、已产生的外部账务,往往只能用反向单据冲正。
- 补偿要幂等且可重试:补偿失败要能反复执行,并有告警与人工兜底。
- 向前恢复 vs 向后恢复:临时故障(下游抖动)应重试正向步骤(向前恢复);业务性失败才补偿(向后恢复)。两者要区分,否则一次网络抖动就触发冲正。
- 隔离问题:Saga 中间状态对外可见,需要业务层缓解——语义锁(标记“处理中”)、交换式更新(先改成中间态)、可重读(结果值带版本号)。
适用与不适用
「适用与不适用」小节链接适用:跨服务长流程(订单履约、开户、理赔)、含人工审批、参与方含外部系统、需要高可用。
不适用:要求瞬间强一致的记账(用同库事务或 TCC)、步骤极少且失败可直接回滚的场景(本地事务 + 重试更简单)。
实现形态与开源参考
「实现形态与开源参考」小节链接Temporal、Camunda / Zeebe、AWS Step Functions、Argo Workflows 提供持久化执行与重试;Seata 提供 Saga 模式;自研时最小实现是“流程状态表 + 步骤任务 + 补偿注册表”。
选型关注四点:状态持久化与重放能力、超时与重试策略是否可声明、补偿是否一等公民、可观测性(能否看清卡在哪一步)。
与其他概念的关系
「与其他概念的关系」小节链接- TCC:TCC 预留资源后再确认,Saga 直接执行后补偿;Saga 对资源冲突更敏感。
- 状态机:Saga 协调器本质是一个状态机,迁移表就是流程定义。
- 领域事件:编排式 Saga 由事件驱动;协调式通常内部命令驱动、对外发事件。
- 对账:Saga 的最终一致仍需对账兜底,尤其是补偿也失败的情况。
常见误区
「常见误区」小节链接| 误区 | 修正 |
|---|---|
| 把补偿写成物理回滚(delete 数据) | 用业务冲正,保留审计轨迹 |
| 没有中间态可见性设计 | 明确“处理中”状态与用户提示,避免重复提交 |
| 协调器无持久化状态 | 进程重启即丢流程,必须落库 |
| 所有失败都触发补偿 | 区分可重试异常与业务失败 |
| 流程散落在事件订阅里无人能看懂 | 步骤多时改用协调器并导出流程图 |
延伸阅读
「延伸阅读」小节链接- Garcia-Molina & Salem 关于 Saga 的原始论文(1987)
- Chris Richardson《微服务架构设计模式》第 4 章(Saga 与隔离缓解)
- Martin Fowler 关于 Process Manager 的论述