前言
参考资料:
《Spring Microservices in Action》
《Spring Cloud Alibaba 微服务原理与实战》
《B站 尚硅谷 SpringCloud 框架开发教程 周阳》
分布式事务是指事务的参与者、支持事务的服务器、资源服务器及事务管理器分别位于分布式系统的不同节点上;
1. 基础知识
1.1 分布式事务问题的理论模型
1.1.1 X/Open 分布式事务模型(XA 协议)
X/Open DTP 包含以下三种角色:
- AP:Application,表示应用程序;
- RM:Resource Manager,表示资源管理器,比如数据库;
- TM:Transaction Manager,表示事务管理器,一般指事务协调者,负责协调和管理事务,提供 AP 编程接口或管理 RM 。可以理解为 Spring 中提供的 Transaction Manager;
-TM 和多个 RM 之间的事务控制,是基于 XA 协议(XASpecification)来完成的。XA 协议是 X/Open 提出的分布式事务处理规范,也是分布式事务处理的工业标准,它定义了 xa_ 和 ax_ 系列的函数原型及功能描述、约束等。目前 Oracle、MySQL、DB2 都实现了 XA 接口,所以它们都可以作为 RM;
1.1.2 两阶段提交协议
两阶段:
- 事务的准备阶段:事务管理器(TM)通知资源管理器(RM)准备分支事务,记录事务日志,并告知事务管理器的准备结果;
- 事务的提交或者回滚阶段:如果所有的资源管理器(RM)在准备阶段都明确返回成功,则事务管理器(TM)向所有的资源管理器(RM)发起事务提交指令完成数据的变更。反之,如果任何一个资源管理器(RM)明确返回失败,则事务管理器(TM)会向所有资源管理器(RM)发送事务回滚指令;
- 优点:简单,降低事务提交失败率;
- 缺点:同步阻塞(对于任何一次指令都必须要有明确的响应才能继续进行下一步)、过于保守(任何一个节点失败都会导致数据回滚);
1.1.3 三阶段提交协议
三阶段:
- CanCommit(询问阶段):事务协调者向参与者发送事务执行请求,询问是否可以完成指令,参与者只需要回答是或者不是即可,不需要做真正的事务操作,这个阶段会有超时中止机制;
- PreCommit(准备阶段):事务协调者会根据参与者的反馈结果决定是否继续执行,如果在询问阶段所有参与者都返回可以执行操作,则事务协调者会向所有参与者发送 PreCommit 请求,参与者收到请求后写 redo 和 undo 日志,执行事务操作但是不提交事务,然后返回 ACK 响应等待事务协调者的下一步通知。如果在询问阶段任意参与者返回不能执行操作的结果,那么事务协调者会向所有参与者发送事务中断请求;
- DoCommit(提交或回滚阶段):这个阶段也会存在两种结果,仍然根据上一步骤的执行结果来决定 DoCommit 的执行方式。如果每个参与者在 PreCommit 阶段都返回成功,那么事务协调者会向所有参与者发起事务提交指令。反之,如果参与者中的任一参与者返回失败,那么事务协调者就会发起中止指令来回滚事务;
- 优点:可以尽早发现无法执行操作而中止后续的行为;在准备阶段后,事务协调者和参与者都引入了超时机制;基于超时机制来避免资源的永久锁定;
- 缺点:一旦超时,仍然可能出现数据不一致的情况;
1.2 分布式事务的两个理论模型
1.2.1 CAP 定理
与《微服务架构 | 3. 注册中心与服务发现》中讲解的一样,指在分布式系统中不可能同时满足一致性(C:Consistency)、可用性(A:Availability)、分区容错性(P:Partition Tolerance)这三个基本需求,最多同时满足两个;
- C:数据在多个副本中要保持强一致,比如前面说的分布式数据一致性问题;
- A:系统对外提供的服务必须一直处于可用状态,在任何故障下,客户端都能在合理的时间内获得服务端的非错误响应;
- P:在分布式系统中遇到任何网络分区故障,系统仍然能够正常对外提供服务;
- 网络分区:不同节点分布在不同的子网络中时,在内部子网络正常的情况下,由于某些原因导致这些子节点之间出现网络不通的情况,导致整个系统环境被切分成若干独立的区域,这就是网络分区;
在分布式系统中,不会选择 CA,而是 AP 和 CP;
- AP:放弃了强一致性,实现最终的一致,是很多互联网公司解决分布式数据一致性问题的主要选择;
- CP:放弃了高可用性,实现强一致性。前面提到的两阶段提交和三阶段提交都采用这种方案。可能导致的问题是用户完成一个操作会等待较长的时间;
- CA:无法同时做到保证数据一致性和可用,要保证数据一致性可能要拒绝客户端请求,除非网络百分百可靠;
1.2.2 BASE 理论
BASE 理论是由于 CAP 中一致性 C 和可用性 A不可兼得而衍生出来的一种新的思想,BASE 理论的核心思想是通过牺牲数据的强一致性来获得高可用性。它有如下三个特性;
- Basically Available(基本可用):分布式系统在出现故障时,允许损失一部分功能的可用性,保证核心功能的可用;
- Soft State(软状态):允许系统中的数据存在中间状态,这个状态不影响系统的可用性,也就是允许系统中不同节点的数据副本之间的同步存在延时;
- Eventually Consistent(最终一致性):中间状态的数据在经过一段时间之后,会达到一个最终的数据一致性;
- BASE 理论并没有要求数据的强一致,而是允许数据在一段时间内是不一致的,但是数据最终会在某个时间点实现一致;
- 在互联网产品中,大部分都会采用 BASE 理论来实现数据的一致,因为产品的可用性对于用户来说更加重要;
- 举个例子,在电商平台中用户发起一个订单的支付,不需要同步等待支付的执行结果,系统会返回一个支付处理中的状态到用户界面。对于用户来说,他可以从订单列表中看到支付的处理结果。而对于系统来说,当第三方的支付处理成功之后,再更新该订单的支付状态即可。在这个场景中,虽然订单的支付状态和第三方的支付状态存在短期的不一致,但是用户却获得了更好的产品体验;
1.3 分布式事务问题的常见解决方案(事务模式)
在互联网场景中更多采用柔性事务,所谓的柔性事务是遵循 BASE 理论来实现的事务模型,它有两个特性:基本可用、柔性状态;
1.3.1 TCC 补偿型方案
TCC(Try-Confirm-Cancel)是一种比较成熟的分布式数据一致性解决方案,它实际上是把一个完整的业务拆分为如下三个步骤:
- Try:这个阶段主要是对数据的校验或者资源的预留(冻结资源);
- Confirm:确认真正执行的任务,只操作 Try 阶段预留的资源(消耗冻结资源);
- Cancel:取消执行,释放 Try 阶段预留的资源(解冻资源);
- 其实 TCC 是一种两阶段提交的思想,第一阶段通过 Try 进行准备工作,第二阶段 Confirm/Cancel 表示 Try 阶段操作的确认和回滚;
- 在一些特殊情况下,服务并没有收到 TCC 事务协调器的 Cancel 或者 Confirm 请求时,可以记录一些分布式事务的操作日志,保存分布式事务运行各个阶段和状态,以实现一致性;
- TCC 服务支持接口调用失败发起重试,所以 TCC 暴露的接口都需要满足幂等性;
1.3.2 基于可靠性消息的最终一致性方案
- 基于可靠性消息的最终一致性是互联网公司比较常用的分布式数据一致性解决方案;
- 它主要利用消息中间件(Kafka、RocketMQ 或 RabbitMQ)的可靠性机制来实现数据一致性的投递;
- 在某些场景中可以牺牲数据的一致性在短时间内不要求实时性,所以可以采用基于可靠性消息的最终一致性方案来保证最终的数据一致性;
- 在消费者没有向消息中间件服务器发送确认时,这个消息会被重复投递,确保消息的可靠性消费;
RocketMQ 使用事件消息模型解决事务问题,其核心是事务回查,主要逻辑如下:
- 生产者发送一个事务消息到消息队列上,消息队列只记录这条消息的数据,此时消费者无法消费这条消息;
- 生产者执行具体的业务逻辑,完成本地事务的操作;
- 接着生产者根据本地事务的执行结果发送一条确认消息给消息队列服务器,如果本地事务执行成功,则发送一个 Commit 消息,表示在第一步中发送的消息可以被消费,否则,消息队列服务器会把第一步存储的消息删除;
- 如果生产者在执行本地事务的过程中因为某些情况一直未给消息队列服务器发送确认,那么消息队列服务器会定时主动回查生产者获取本地事务的执行结果,然后根据回查结果来决定这条消息是否需要投递给消费者;
- 消息队列服务器上存储的消息被生产者确认之后,消费者就可以消费这条消息,消息消费完成之后发送一个确认标识给消息队列服务器,表示该消息投递成功;
1.3.3 最大努力通知型
- 与基于可靠性消息的最终一致性方案类似,适用于对数据一致性要求不高的场景;
- 在支付服务没有返回一个消息确认时,支付宝会不断进行重试,直到一个消息确认或达到最大重试次数;
1.3.4 AT 模式
AT 模式是 Seata 最主推的分布式事务解决方案,它是基于 XA 演进而来的一种分布式事务模式。分为三大模块:TM、RM 和 TC(与XA不同)。其中:
- TM 事务管理器:负责向 TC 注册一个全局事务,并生成一个全局唯一的 XID。作为 Seata 的客户端与业务系统集成;
- RM 数据库资源:在业务层面通过 JDBC 标准的接口访问 RM 时, Seata 会对所有请求进行拦截。作为 Seata 的客户端与业务系统集成;
- TC 事务协调器:每个本地事务进行提交时,RM 都会向 TC 注册一个分支事务。作为 Seata 的服务器独立部署;
- AT 模式和 XA 一样,也是一个两阶提交事务模型;
1.3.5 Saga 模式
- Saga 模式又称为长事务解决方案,主要描述的是在没有两阶段提交的情况下如何解决分布式事务问题;
- 其核心思想是:把一个业务流程中的长事务拆分为多个本地短事务,业务流程中的每个参与者都提交真实的提交给该本地短事务,当其中一个参与者事务执行失败,则通过补偿机制补偿前面已经成功的参与者;
- Saga 的机制相关详情请见笔者的另一篇文章:《微服务架构设计模式》读书笔记 | 第4章 使用Saga管理事务;
1.5 目前几种流行的分布式事务技术方案对比
名称 | 厂商 | 特点(优点) | 缺点 |
---|---|---|---|
Seata | Alibaba | 对业务无侵入、高性能 | Seata 是工作在读未提交的隔离级别,Seata 本身存在一定的性能损耗 |
2. Seata
Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务;它提供了 AT、TCC、Saga 和 XA 事务模式,为开发者提供了一站式的分布式事务解决方案;