文章目录
- 前言
- 一、分布式事务是什么?
- 二、分布式事务的理论基础:
- 2.1. CAP定理:
- 2.1.1 CAP定理介绍:
- 2.1.2 AP VS CP:
- 2.1.3 CAP 定理的误解:
- 2.2. Base 理论:
- 2.3. CAP定理和BASE理论的关系:
- 三、分布式事务的解决方案:
- 3.1 XA 分布式事务(强一致性事务):
- 3.1.1 XA分布式事务原理:
- 3.1.2 二阶段提交过程:
- 3.1.2 二阶段提交失败处理:
- 3.1.3 三阶段提交过程:
- 3.2 TCC补偿性事务解决方案:
- 3.3 事务消息:
- 总结:
前言
随着微服务的兴起,当之前出现在单体服务中的事务,在多个服务节点中如何保证数据的一致性,本文对此进行介绍。
一、分布式事务是什么?
分布式事务是指在分布式系统中,涉及多个独立服务或数据库的操作需要保持一致性的执行的一种机制。传统的单体应用中,事务由数据库本身来提供,而在分布式系统中,由于数据分布在不同的节点上,因此无法直接使用单个数据库的事务来保证一致性。在分布式系统中,分布式事务需要满足 ACID(原子性、一致性、隔离性和持久性)的特性:
-
原子性(Atomicity):一个事务被视为一个不可分割的最小工作单元,事务中的所有操作要么全部成功,要么全部失败。如果任何一个操作失败,整个事务将会被回滚,使系统保持一致性。
-
一致性(Consistency):事务执行前后,系统的状态必须保持一致。事务在开始之前和结束之后都遵循定义的一致性规则,保证事务在执行过程中不会破坏数据的完整性。
-
隔离性(Isolation):事务的执行在逻辑上是相互隔离的,一个事务的执行不能其他事务所干扰,保证每个事务在执行时感受不到其他事务的存在。
-
持久性(Durability):事务一旦提交,其结果应该是永久性的,即使系统发生故障或宕机,也能够保持已提交的事务。
二、分布式事务的理论基础:
2.1. CAP定理:
2.1.1 CAP定理介绍:
CAP定理是分布式系统设计中的基本原则,指出在一个分布式系统中,Consistency(一致性)、Availability(可用性)和Partition tolerance(分区容错性)这三个属性无法同时满足。根据CAP定理,一个分布式系统只能满足其中两个属性。
由于网络的不确定性所有P 肯定存在,C和A 肯定是矛盾的;要么随时高可用来看保证强一致性(AP),要不损失强一致性来保证高可用性(CP);
C(一致性)和A(可用性)不能同时满足的原因是基于CAP定理(CAP theorem),该定理指出在面对网络分区(节点之间的通信中断)时,为了保证系统的可用性,必须放弃一致性。
在一个分布式系统中,节点之间需要进行数据的复制和同步以保持一致性。当网络分区发生时,即节点之间无法通信时,为了保证可用性,部分节点可能会继续提供服务。然而,如果这些节点允许独立更新数据,就会导致数据的不一致性。
为了保持一致性,所有节点必须在同一时间点看到相同的数据状态。但在面对网络分区时,为了保证可用性,可能需要允许部分节点独立更新数据,这就会导致数据的不一致性。因此,C和A不能同时满足。
在CAP定理中,P(分区容错性)是不可避免的,因为网络分区是无法完全避免的。因此,在面对网络分区时,可以选择满足CA(一致性和可用性)或者CP(一致性和分区容错性)。具体的选择取决于应用场景和需求。
对于 CAP 来说,放弃强一致性,追求分区容错性和可用性,是很多分布式系统设计时的选择。在工程实践中,基于 CAP 定理逐步演化,出现了 Base 理论。
2.1.2 AP VS CP:
由于在分布式系统中,网络错误是不可避免的,因此总是需要具备分区容错性P。因此在存在分区容错性的情况下,我们只能对A和P二选一。
AP(Availability and Partition tolerance):当可用性高于一致性时,系统将始终处理客户端请求并尝试返回最新可用版本的信息,即使由于网络分区而无法保证它是最新的。
CP(Consistency and Partition tolerance ):如果选择一致性而不是可用性,则系统将返回错误或超时,如果由于网络分区或故障而无法更新到其他节点,则该系统将返回错误或超时。
在实际中的分布式框架中,我们一般会把如ZK认为是属于CP系统,对于Eureka这类的认为是AP系统。当然这种简单的把系统划分为AP或者CP是具有争议的,因为目前很多系统都会支持不同的运行模式,同时也会通过一些手段去尽可能的提升A&C。
举个例子:
假设我们的分布式系统内部出现了网络故障,由于我们需要具备分区容错性,因此此时系统应该正常工作。
此时client向服务器Server1 发送了写请求,S1接收并处理了请求。
如果我们系统要保证一致性,那么我们必须要等到S1将数据同步到S2后,才能够返回给客户端成功状态。但是由于网络故障,S1无法同步到S2,因此此时系统就不可用了。
那如果我们要保证系统的可用性,那么就应该直接返回成功,而无需等待S1同步S2。此时如果客户端再次向S2发送读请求,那么S2服务器此时只能返回旧的数据。这也就意味着我们无法保证系统的数据一致性。
2.1.3 CAP 定理的误解:
CAP 定理经常被误解为必须始终在三个保证中选择两个。实际上,只有在网络分区或发生故障时,才需要在一致性和可用性之间进行选择。在没有网络分区或网络故障的情况下,可以同时满足可用性和一致性。
2.2. Base 理论:
BASE理论是分布式系统设计中的一种理论框架,它是对ACID(原子性、一致性、隔离性和持久性)原则的一种补充和扩展。BASE是指基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)这三个概念。
- BA 基本可用(Basically Available):系统必须保证在出现故障或异常情况下,仍能够基本正常地对外提供服务。即使在某些情况下,系统的性能或功能有所降级,但仍然能够保持可用性。
- S 软状态(Soft State):分布式系统中的数据状态不需要实时保持一致,允许在一段时间内是部分一致的。这意味着,在不同节点之间的数据同步可能存在一定的延迟,导致系统中的数据状态在某个时刻是不完全一致的。
- C 最终一致性(Eventually Consistent):最终一致性是指在经过一段时间后,分布式系统中的所有节点最终会达到一致的状态。即使在分布式系统中,数据在某个时刻可能是部分一致的,但随着时间的推移,系统会自动进行数据同步和调整,最终达到一致;
BASE理论通过降低一致性要求,提高系统的可用性和性能,适用于一些对数据一致性要求相对较低的场景,如互联网应用中的分布式存储、缓存系统等。相比于ACID原则,BASE理论更加适合大规模分布式系统的设计和实现。
2.3. CAP定理和BASE理论的关系:
- CAP定理指出,在分布式系统中无法同时满足一致性、可用性和分区容错性。
分布式事务需要考虑如何在面临网络分区和节点故障时保证数据的一致性和可用性
。 - BASE理论提出了一种放宽ACID事务特性的思路,
强调最终一致性和柔性状态
。在分布式事务中,可以根据具体需求和业务场景选择适合的一致性级别,如强一致性、最终一致性或柔性状态。
在实际应用中,分布式事务的设计需要考虑CAP定理和BASE理论的影响,根据业务需求、系统规模和性能要求进行权衡和折衷。
三、分布式事务的解决方案:
3.1 XA 分布式事务(强一致性事务):
3.1.1 XA分布式事务原理:
XA 协议:XA 协议是由 X/Open 组织提出的分布式事务处理规范,主要定义了事务管理器 TM 和局部资源管理器 RM 之间的接口。目前主流的数据库,比如 oracle、DB2,MYSQL 都是支持 XA 协议的。
基于XA 协议的XA分布式事务,将事务的提交分成了两个阶段:也就是2PC (tow phase commit),XA协议就是通过将事务的提交分为两个阶段来实现分布式事务
。
- AP 应用系统,先向TM(全局事务管理) 注册一个全局事务;
- 注册完成,向各个资源端发送请求,各个资源端各自开启自己的本地事务;
- 各个资源端 ,完成事务后,向 AP 返回事务的状态(回滚或者提交);
- AP 将各个资源的事务状态提交个TM ,TM控制各个资源端事务的回滚或者提交;
缺点: AP 在等待资源端返回事务状态的等待时间没有做限制,如果没有返回,则一直阻塞
;
3.1.2 二阶段提交过程:
二阶段提交(Two-Phase Commit,简称2PC)是一种分布式系统中保证事务的原子性和一致性的协议。它由一个协调者(coordinator)和多个参与者(participants)组成。在二阶段提交协议中,事务的提交过程分为两个阶段:
- 准备阶段(Prepare Phase):协调者向所有参与者发送事务提交请求,并等待参与者的响应。参与者执行事务操作,并将操作的结果和准备就绪(Prepare)或中止(Abort)的响应发送给协调者(各个 参与者 节点执行本地事务操作,
但在执行完成后并不会真正提交数据库本地事务
,而是先向 协调者 报告说:“我这边可以处理了/我这边不能处理”。.)。 - 提交阶段(Commit Phase):
如果所有参与者都准备就绪,协调者向所有参与者发送提交请求
。参与者在收到提交请求后,执行事务的最终提交,并将提交完成的消息发送给协调者。协调者在收到所有参与者的提交完成消息后,向所有参与者发送最终的提交结果。
二阶段提交协议的基本原理是协调者通过两个阶段的消息交互来确保所有参与者的一致性决策,并最终决定是否提交事务。如果任何一个参与者在准备阶段中返回中止响应,则协调者会发送中止请求,使所有参与者回滚事务。只有当所有参与者都返回准备就绪响应,且协调者在提交阶段中收到所有参与者的提交完成消息时,才会执行最终提交
。
二阶段提交协议的优点是能够保证分布式系统中事务的一致性,但也存在一些问题,如单点故障、阻塞等,因此在实际应用中,还需要考虑其他的协议或算法来解决这些问题。
3.1.2 二阶段提交失败处理:
在两阶段提交(Two-Phase Commit,简称2)协议的第二个阶段,协调者(Coordinator)会向各个参与者(Participants)发送commit(提交)或者abort(中止)命令。如果某个资源端执行命令失败,可能会发生以下情况:
- 协调者无法收到资源端的响应:如果协调者在一定时间内无法收到资源端的响应,它可能会认为该资源端已经失败,并采取相应的恢复措施,如中止整个事务。
- 资源端执行commit命令失败:如果某个资源端在接收到commit命令后执行失败,它会向协调者发送一个失败的响应。协调者会根据这个响应来决定是否中止整个事务。
- 资源端执行callback命令失败:在一些情况下,协调者可能需要在事务完成后通知资源端执行一些后续操作,这时会发送callback命令。如果某个资源端在执行callback命令时失败,协调者可能会重新尝试发送callback命令,或者采取其他的恢复措施。
总之,如果某个资源端执行命令失败,协调者会根据失败的情况来决定是否中止整个事务或采取其他的恢复措施,以确保事务的一致性。
3.1.3 三阶段提交过程:
针对二阶段提交存在的问题,三阶段提交协议在prepare与commit阶段之间增加一个pre-commit阶段。Prepare阶段只询问参与者而不做事务,而在pre-commit阶段各个参与者才会执行本地事务但不提交。Commit阶段就是直接提交。这样做可以避免二阶段当协调者迟迟没有发出commit或者rollback通知,参与者在超时后可以自行提交或者回滚,避免阻塞事务(这是因为经过了prepare阶段已经确认了各个参与者是可以执行的,最后第三阶段直接执行即可)。 三阶段提交也存在很多问题,也不能完全保证数据一致,完全一致需要用到Paxos算法。
- 三阶段的第一阶段:开启 xa 事务,这里 xid 为全局事务 id:
XA {START|BEGIN} xid [JOIN|RESUME]
结束 xa 事务:
XA END xid [SUSPEND [FOR MIGRATE]] - 三阶段的第二阶段,即 prepare:
XA PREPARE xid - 三阶段的第三阶段,即 commit/rollback:
XA COMMIT xid [ONE PHASE]XA ROLLBACK xid - 查看处于 PREPARE 阶段的所有事务:
XA RECOVER XA RECOVER [CONVERT XID]
3.2 TCC补偿性事务解决方案:
TCC分别对应Try、Confirm和Cancel三种操作,含义如下:
- Try:预留业务资源
- Confirm:确认执行业务操作,执行事务
- Cancel:取消执行业务操作
TCC解决了跨应用业务操作的原子性问题,在诸如组合支付、账务拆分场景非常实用。TCC实际上把数据库层的二阶段提交上提到了应用层来实现,对于数据库来说是一阶段提交,规避了数据库层的2PC性能低下问题。TCC需要业务提供使用,开发复杂和成本高。
3.3 事务消息:
基于消息中间件的事务消息来完成分布式事务。事务消息可以确保本地执行事务与消息发送是原子的:先发送一条消息到消息中间件,然后执行本地事务,当本地事务成功后再发送提交确认到消息中间件,然后这条消息才能被其他业务消费者所能感知,从而确保原子性。
以RocketMq 为例
- 生产者发送到mq 的消息时half 半消息不能消费者使用;
- mq 端发起消息的check 给生产端,生产端返回结果给到mq;
- mq 根据看结果 来判断是否改条消息对消费端可见;
总结:
在微服务中,服务之间的通信以及分布式事务,是绕不过去的问题,在Cap和Base 理论的支持下,出现了基于强一致性和最终一致性的 分布式事务解决方案。