本文来说下分布式事务模型之Saga
概述
事务是一组不可分组的操作集合,这些操作要么都成功执行,要么都取消执行。最典型的需要事务的场景是银行账户间的转账:假如 A 账户要给 B 账户转账 100 元,那么 A 账户要扣减 100 元,B 账户要增加 100 元,这两个账户的数据变更都成功才可算作转账成功。更严格来说,可以用 ACID 四个特性表述事务:
- Atomicity:原子性,事务中的所有操作要么都成功执行,要么都取消执行,不能存在部分执行,部分不执行的状态。
- Consistency:一致性,举个例子简单的理解就是,A、B 两个账户各有 100 元,无论两个账户并发相互转账多少次,两个账户的资金总额依然是 200 元。
- Isolation:隔离性,并发事务之间的相互影响程度,隔离性也是分级别的:读未提交、读已提交、可重复读等。
- Durability:持久性,事务完成后对数据的更改不会丢失。
单体数据库不涉及网络交互,所以在多表之间实现事务是比较简单的,这种事务我们称之为本地事务。
但是单体数据库的性能达到瓶颈的时候,就需要分库(分物理实例),就会出现跨库(数据库实例)的事务需求;随着企业应用的规模越来越大,企业会进一步进行服务化改造,以满足业务增长的需求;当前微服务架构越来越流行,跨服务的事务场景也会越来越多。
这些都是分布式事务的需求。分布式事务是指是指事务的发起者、参与者、数据资源服务器以及事务管理器分别位于分布式系统的不同节点之上。
概括起来,分布式事务有三种场景:
- 跨数据库分布式事务
- 跨服务分布式事务
- 混合式分布式事务
分布式事务中涉及的参与者分布在异步网络中,参与者通过网络通信来达到分布式一致性,网络通信不可避免出现失败、超时的情况,因此分布式事务的实现比本地事务面临更多的困难。下面介绍下常见的分布式事务解决方案之Saga模型。
Saga
Saga 并不是一个新概念,其相关论文在 1987 年就发布了,和 XA 两阶段提交规范出现的时间差不多。
Saga 和 TCC 一样,也是一种补偿事务,但是它没有 try 阶段,而是把分布式事务看作一组本地事务构成的事务链。
事务链中的每一个正向事务操作,都对应一个可逆的事务操作。Saga 事务协调器负责按照顺序执行事务链中的分支事务,分支事务执行完毕,即释放资源。如果某个分支事务失败了,则按照反方向执行事务补偿操作。
假如一个 Saga 的分布式事务链有 n 个分支事务构成,[T1,T2,…,Tn],那么该分布式事务的执行情况有三种:
- T1,T2,…,Tn:n 个事务全部执行成功了。
- T1,T2,…,Ti,Ci,…,C2,C1:执行到第 i (i<=n) 个事务的时候失败了,则按照 i->1 的顺序依次调用补偿操作。如果补偿失败了,就一直重试。补偿操作可以优化为并行执行。
- T1,T2,…,Ti (失败),Ti (重试),Ti (重试),…,Tn:适用于事务必须成功的场景,如果发生失败了就一直重试,不会执行补偿操作。
举个例子
假如国庆节小明要出去玩,从北京出发,先去伦敦,在伦敦游玩三天,再去巴黎,在巴黎游玩三天,然后再返回北京。整个行程中涉及不同航空公司的机票预订以及伦敦和巴黎当地的酒店预订,小明的计划是如果任何一张机票或酒店预订不上,就取消本次出行计划。假如综合旅游出行服务平台提供这种一键下单的功能,那么这就是一个长事务,用 Saga 模式编排服务的话,就如下图所示:任何一个环节失败的话,就通过补偿操作取消前面的行程预订。
特点剖析
Saga 事务是可以保障事务的三个特性:
- 原子性:Saga 协调器可以协调事务链中的本地事务要么全部提交,要么全部回滚。
- 一致性:Saga 事务可以实现最终一致性。
- 持久性:基于本地事务,所以这个特性可以很好实现。
但是 Saga 不保证事务隔离性的,本地事务提交后变更就对其他事务可见了。其他事务如果更改了已经提交成功的数据,可能会导致补偿操作失败。比如扣款失败,但是钱已经花掉了,业务设计上需要考虑这种场景并从业务设计上规避这种问题。
Saga 事务和 TCC 事务一样,对业务实现要求高,要求业务设计实现上遵循三个策略:
- 允许空补偿:网络异常导致事务的参与方只收到了补偿操作指令,因为没有执行过正常操作,因此要进行空补偿。
- 保持幂等性:事务的正向操作和补偿操作都可能被重复触发,因此要保证操作的幂等性。
- 防止资源悬挂:网络异常导致事务的正向操作指令晚于补偿操作指令到达,则要丢弃本次正常操作,否则会出现资源悬挂问题。
虽然 Saga 和 TCC 都是补偿事务,但是由于提交阶段不同,所以两者也是有不同的:
- Saga 是不完美补偿,补偿操作会留下之前原始事务操作的痕迹,需要考虑对业务上的影响。
- TCC 是完美补偿,补偿操作会彻底清理之前的原始事务操作,用户是感知不到事务取消之前的状态信息的。
- TCC 的事务可以更好的支持异步化,但是 Saga 模式一般在补偿阶段比较适合异步化。
Saga 模式非常适合于业务流程长的长事务的场景,实现上对业务侵入低,所以非常适合微服务架构的场景。同时 Saga 采用的是一阶段提交模式,不会对资源长时间加锁,不存在“木桶效应”,所以采用这种模式架构的系统性能高、吞吐高。
阿里巴巴的 Seata 开源项目和华为的 ServiceComb 开源项目都支持 Saga 模式。
本文小结
本文详细介绍了分布式事务解决方案之Saga模型,后续会对其他相关知识进行深入的介绍和分析。