5.3.3 Saga

Saga 事务模式历史悠久,早于分布式事务概念的提出。

Saga 起源于 1987 年普林斯顿大学的 Hector Garcaa-Molina 和 Kenneth Salem 在 ACM 发表的论文《SAGAS》[1]。该论文提出了一种提高“长时间事务”(Long Lived Transaction)效率的方法,核心思路是将一个大事务分解为多个可以交错运行的子事务,并在每个子事务中引入补偿操作。补偿(也称逆向恢复)指的是在分布式事务出现异常时,通过一系列的操作,尽可能使得分布式事务状态回滚到之前的状态,从而避免分布式事务产生不一致的情况。

Saga 事务模型由两部分操作组成:

  1. 一部分是将大事务 T 拆分成若干小事务,命名为 T1,T2,Tn。每个子事务被应被视为原子行为,如果分布式事务 T 能够正常提交,那么它对数据的影响应该与连续按顺序成功提交子事务 Ti 等价。
  2. 另一部分是为每个子事务设计对应的补偿动作,命名为 C1,C2,Cn。Ti 与 Ci 满足以下条件:
    • Ti 与 Ci 具备幂等性。
    • Ti 与 Ci 满足交换律,即无论先执行 Ti 还是先执行 Ci,其效果都是一样的。
    • Ci 必须能成功提交,即不考虑 Ci 的失败回滚情况,如果出现失败持续重试直至成功或者被人工介入为止。

如果 T1 到 Tn 均执行成功,那么整个事务顺利完成,否则根据下面两种机制之一进行事务恢复。

  • 正向操作(Forward Recovery)如果 Ti 提交失败,则一直对 Ti 进行重试,直至成功为止(使用最大努力交付机制)。这种恢复方式不需要进行补偿,适用于事务最终都要执行成功的情况。如订单服务中银行已经扣款,那么就一定要发货。
  • 逆向恢复(Backward Recovery)如果 Ti 提交失败,则执行对应的补偿 Ci,直至恢复到 Ti 之前的状态,这里要求 Ci 必须成功(使用最大努力交付机制)。

图 5-4 Saga 事务模型

Saga 模式非常适合处理流程较长且需要确保事务最终一致性的业务操作。例如,一个旅游预订平台,用户可以同时预订机票、酒店和租车服务,这三项服务可能由不同的微服务或第三方供应商提供。这个场景中,Saga 事务模型允许系统逐步执行每个操作,并在任一步骤失败时有序地进行补偿操作,从而确保系统的一致性和提升用户体验。

与 TCC 相比,Saga 通常采用事件驱动设计,即每个服务都是异步执行的,无需设计资源的冻结状态或处理撤销冻结的操作。然而,这种方式也存在一些问题,比如缺乏隔离性,多个 Saga 事务同时操作同一数据源时,因缺乏隔离机制,操作无法保证原子性,可能导致数据被覆盖的情况。

最后,尽管补偿操作相对容易实现,但确保正向操作与补偿操作的严格执行仍需投入大量精力。因此,Saga 事务通常不通过裸编码实现,而是在事务中间件的支持下完成。前面提到的 TCC 事务模型中,Seata 中间件也同样支持 Saga 事务模型。


  1. 参见 https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf ↩︎

总字数:947
Last Updated:
Contributors: isno