4. Saga 模式核心概念
Saga 模式通过将长跨度分布式事务拆解为一系列本地事务,并引入补偿机制来保证最终一致性。理解其四个核心概念——本地事务、补偿事务、Saga 执行器和Saga 日志——是掌握该模式的基础。
4.1 本地事务 (Local Transaction)
本地事务是 Saga 中的最小工作单元,指在单个数据库或服务实例内部执行的 ACID 事务。每个 Saga 步骤对应一个本地事务,它独立提交或回滚,不依赖外部协调者。
| 特性 | 说明 |
|---|---|
| 原子性 | 本地事务内的所有操作要么全部成功,要么全部失败 |
| 隔离性 | 本地事务提交后,其结果立即对后续 Saga 步骤可见 |
| 持久性 | 一旦提交,数据变更永久保存 |
| 无跨服务依赖 | 不持有跨服务的分布式锁或资源 |
设计要点:本地事务应尽量短小精悍,避免在事务内执行远程调用或长时间 I/O 操作,防止数据库连接池耗尽。
4.2 补偿事务 (Compensating Transaction)
补偿事务是 Saga 模式的核心容错机制。当 Saga 中的某个本地事务失败时,系统需要反向执行之前已成功提交的本地事务的补偿操作,以撤销其业务影响。
- 幂等性:补偿事务必须支持幂等调用,避免因重试导致数据重复或错误。
- 可交换性:补偿事务与正向事务的执行顺序无关,最终结果一致。
- 业务语义:补偿不是简单的数据回滚,而是执行具有业务意义的反向操作(如“取消订单”补偿“创建订单”)。
正向事务 vs 补偿事务示例:
正向:扣减库存 → 补偿:增加库存
正向:创建订单 → 补偿:取消订单(状态置为已取消)
正向:扣款 → 补偿:退款
正向:扣减库存 → 补偿:增加库存
正向:创建订单 → 补偿:取消订单(状态置为已取消)
正向:扣款 → 补偿:退款
4.3 Saga 执行器 (Saga Executor)
Saga 执行器是编排或协调 Saga 流程的运行时组件。它负责按顺序调用本地事务,并在失败时触发补偿流程。根据编排方式,执行器分为两种模式:
| 模式 | 描述 | 典型实现 |
|---|---|---|
| 编排模式 (Choreography) | 每个服务在本地事务完成后,通过事件触发下一个服务 | 事件总线、消息队列 |
| 协调模式 (Orchestration) | 中央协调器(Orchestrator)负责调度所有步骤和补偿 | 状态机、工作流引擎 |
注意:协调模式虽然控制逻辑集中,但协调器本身可能成为单点瓶颈;编排模式去中心化,但事件追踪和调试复杂度较高。
4.4 Saga 日志 (Saga Log)
Saga 日志是记录 Saga 执行轨迹的持久化存储,用于故障恢复、审计和监控。每条日志记录一个 Saga 实例的生命周期事件。
日志核心字段
| 字段 | 类型 | 说明 |
|---|---|---|
| SagaId | UUID | 全局唯一标识一次 Saga 执行 |
| StepId | 整数 | 当前步骤序号 |
| Action | 字符串 | 操作类型:START / TX_COMMIT / TX_FAIL / COMPENSATE / SAGA_END |
| Payload | JSON | 请求参数或补偿所需上下文 |
| Timestamp | DateTime | 事件发生时间 |
| Status | 枚举 | SUCCESS / FAILED / PENDING |
日志在故障恢复中的作用
- 正向恢复:Saga 执行器重启后,从日志中读取最后一个成功步骤,继续执行后续未完成的本地事务。
- 逆向恢复:当检测到不可恢复的失败时,执行器根据日志逆向执行所有已成功步骤的补偿事务。
- 幂等校验:通过日志中的 SagaId + StepId 唯一索引,防止重复执行或重复补偿。
日志写入策略:建议在本地事务提交之前写入 Saga 日志(先写日志,后提交事务),确保日志与业务状态一致。若先提交事务再写日志,系统崩溃可能导致日志丢失,造成补偿遗漏。
4.5 核心概念关系总结
四个核心概念协同工作,构成 Saga 模式的完整运行时:
- 本地事务是执行单元,补偿事务是安全网。
- Saga 执行器是大脑,负责决策何时执行正向或补偿流程。
- Saga 日志是记忆体,确保系统在崩溃后能准确恢复执行状态。
实践建议:在实现 Saga 时,优先设计好补偿事务的幂等性和日志的持久化策略。这两个点往往是分布式事务在生产环境中稳定运行的关键保障。