5种分布式事务解决⽅案优缺点对⽐
转载⾃:
背景
分布式事务是企业集成中的⼀个技术难点,也是每⼀个分布式系统架构中都会涉及到的⼀个东西,特别是在微服务架构中,⼏乎可以说是⽆法避免。
ACID
指数据库事务正确执⾏的四个基本要素:
1. 原⼦性(Atomicity)
2. ⼀致性(Consistency)
3. 隔离性(Isolation)
4. 持久性(Durability)
CAP
CAP原则⼜称CAP定理,指的是在⼀个分布式系统中,⼀致性(Consistency)、可⽤性(Availability)、分区容忍性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
⼀致性:在分布式系统中的所有数据备份,在同⼀时刻是否同样的值。
可⽤性:在集中⼀部分节点故障后,集整体是否还能响应客户端的读写请求。
分区容忍性:以实际效果⽽⾔,分区相当于对通信的时限要求。系统如果不能在时限内达成数据⼀致性,就意味着发⽣了分区的情况,必须就当前操作在C和A之间做出选择。
BASE理论
BASE理论是对CAP中的⼀致性和可⽤性进⾏⼀个权衡的结果,理论的核⼼思想就是:我们⽆法做到强⼀致,但每个应⽤都可以根据⾃⾝的业务特点,采⽤适当的⽅式来使系统达到最终⼀致性。
Basically Available(基本可⽤)
Soft state(软状态)
Eventually consistent(最终⼀致性)
解决⽅案
01 两阶段提交(2PC)
两阶段提交2PC是分布式事务中最强⼤的事务类型之⼀,两段提交就是分两个阶段提交,第⼀阶段询问各个事务数据源是否准备好,第⼆阶段才真正将数据提交给事务数据源。
为了保证该事务可以满⾜ACID,就要引⼊⼀个协调者(Cooradinator)。其他的节点被称为参与者(Participant)。协调者负责调度参与者的⾏为,并最终决定这些参与者是否要把事务进⾏提交。处理流程如下:
阶段⼀
a) 协调者向所有参与者发送事务内容,询问是否可以提交事务,并等待答复。
b) 各参与者执⾏事务操作,将 undo 和 redo 信息记⼊事务⽇志中(但不提交事务)。
c) 如参与者执⾏成功,给协调者反馈 yes,否则反馈 no。
阶段⼆
如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(rollback)消息;否则,发送提交(commit)消息。两种情况处理如下:
情况1:当所有参与者均反馈 yes,提交事务
a) 协调者向所有参与者发出正式提交事务的请求(即 commit 请求)。
b) 参与者执⾏ commit 请求,并释放整个事务期间占⽤的资源。
c) 各参与者向协调者反馈 ack(应答)完成的消息。
d) 协调者收到所有参与者反馈的 ack 消息后,即完成事务提交。
情况2:当有⼀个参与者反馈 no,回滚事务
a) 协调者向所有参与者发出回滚请求(即 rollback 请求)。
b) 参与者使⽤阶段 1 中的 undo 信息执⾏回滚操作,并释放整个事务期间占⽤的资源。
c) 各参与者向协调者反馈 ack 完成的消息。
d) 协调者收到所有参与者反馈的 ack 消息后,即完成事务。
问题
1) 性能问题:所有参与者在事务提交阶段处于同步阻塞状态,占⽤系统资源,容易导致性能瓶颈。
2) 可靠性问题:如果协调者存在单点故障问题,或出现故障,提供者将⼀直处于锁定状态。
3) 数据⼀致性问题:在阶段 2 中,如果出现协调者和参与者都挂了的情况,有可能导致数据不⼀致。
优点:尽量保证了数据的强⼀致,适合对数据强⼀致要求很⾼的关键领域。(其实也不能100%保证强⼀致)。
缺点:实现复杂,牺牲了可⽤性,对性能影响较⼤,不适合⾼并发⾼性能场景。
02 三阶段提交(3PC)
三阶段提交是在⼆阶段提交上的改进版本,3PC最关键要解决的就是协调者和参与者同时挂掉的问题,所以3PC把2PC的准备阶段再次⼀分为⼆,这样三阶段提交。处理流程如下:
阶段⼀
a) 协调者向所有参与者发出包含事务内容的 canCommit 请求,询问是否可以提交事务,并等待所有参与者答复。
b) 参与者收到 canCommit 请求后,如果认为可以执⾏事务操作,则反馈 yes 并进⼊预备状态,否则反馈 no。
阶段⼆
协调者根据参与者响应情况,有以下两种可能。
情况1:所有参与者均反馈 yes,协调者预执⾏事务
a) 协调者向所有参与者发出 preCommit 请求,进⼊准备阶段。
b) 参与者收到 preCommit 请求后,执⾏事务操作,将 undo 和 redo 信息记⼊事务⽇志中(但不提交事务)。
c) 各参与者向协调者反馈 ack 响应或 no 响应,并等待最终指令。
情况2:只要有⼀个参与者反馈 no,或者等待超时后协调者尚⽆法收到所有提供者的反馈,即中断事务
a) 协调者向所有参与者发出 abort 请求。
b) ⽆论收到协调者发出的 abort 请求,或者在等待协调者请求过程中出现超时,参与者均会中断事务。
阶段三
该阶段进⾏真正的事务提交,也可以分为以下两种情况。
情况 1:所有参与者均反馈 ack 响应,执⾏真正的事务提交
a) 如果协调者处于⼯作状态,则向所有参与者发出 do Commit 请求。
b) 参与者收到 do Commit 请求后,会正式执⾏事务提交,并释放整个事务期间占⽤的资源。
c) 各参与者向协调者反馈 ack 完成的消息。
d) 协调者收到所有参与者反馈的 ack 消息后,即完成事务提交。
情况2:只要有⼀个参与者反馈 no,或者等待超时后协调组尚⽆法收到所有提供者的反馈,即回滚事务。
a) 如果协调者处于⼯作状态,向所有参与者发出 rollback 请求。
b) 参与者使⽤阶段 1 中的 undo 信息执⾏回滚操作,并释放整个事务期间占⽤的资源。
c) 各参与者向协调组反馈 ack 完成的消息。
d) 协调组收到所有参与者反馈的 ack 消息后,即完成事务回滚。
优点:相⽐⼆阶段提交,三阶段提交降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免了协调者单点问题。阶段 3 中协调者出现问题时,参与者会继续提交事务。
缺点:数据不⼀致问题依然存在,当在参与者收到 preCommit 请求后等待 do commite 指令时,此时如果协调者请求中断事务,⽽协调者⽆法与参与者正常通信,会导致参与者继续提交事务,造成数据不⼀致。
03 补偿事务(TCC)
TCC 是服务化的⼆阶段编程模型,采⽤的补偿机制:
条件:
需要实现确认和补偿逻辑
需要⽀持幂等
处理流程:
a) Try 阶段主要是对业务系统做检测及资源预留。
这个阶段主要完成:
完成所有业务检查( ⼀致性 ) 。
预留必须业务资源( 准隔离性 ) 。
Try 尝试执⾏业务。
b) Confirm 阶段主要是对业务系统做确认提交。
Try阶段执⾏成功并开始执⾏ Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm⼀定成功。
c) Cancel 阶段主要是在业务执⾏错误,需要回滚的状态下执⾏的业务取消,预留资源释放。
优点:
性能提升:具体业务来实现控制资源锁的粒度变⼩,不会锁定整个资源。
数据最终⼀致性:基于 Confirm 和 Cancel 的幂等性,保证事务最终完成确认或者取消,保证数据的⼀致性。
可靠性:解决了 XA 协议的协调者单点故障问题,由主业务⽅发起并控制整个业务活动,业务活动管理器也变成多点,引⼊集。
缺点:TCC 的 Try、Confirm 和 Cancel 操作功能要按具体业务来实现,业务耦合度较⾼,提⾼了开发成本。
04 本地消息表(消息队列)
其核⼼思想是将分布式事务拆分成本地事务进⾏处理。
⽅案通过在消费者额外新建事务消息表,消费者处理业务和记录事务消息在本地事务中完成,轮询事务消息表的数据发送事务消息,提供者基于消息中间件消费事务消息表中的事务。
条件:
服务消费者需要创建⼀张消息表,⽤来记录消息状态。
分布式和微服务的关系服务消费者和提供者需要⽀持幂等。
需要补偿逻辑。
每个节点上起定时线程,检查未处理完成或发出失败的消息,重新发出消息,即重试机制和幂等性机制。
处理流程:
1. 服务消费者把业务数据和消息⼀同提交,发起事务。
2. 消息经过MQ发送到服务提供⽅,服务消费者等待处理结果。
3. 服务提供⽅接收消息,完成业务逻辑并通知消费者已处理的消息。
容错处理情况如下:
当步骤1处理出错,事务回滚,相当于什么都没有发⽣。
当步骤2、3处理出错,由于消息保存在消费者表中,可以重新发送到MQ进⾏重试。
如果步骤3处理出错,且是业务上的失败,服务提供者发送消息通知消费者事务失败,且此时变为消费者发起回滚事务进⾏回滚逻辑。
优点:从应⽤设计开发的⾓度实现了消息数据的可靠性,消息数据的可靠性不依赖于消息中间件,弱化了对 MQ 中间件特性的依赖。
缺点:与具体的业务场景绑定,耦合性强,不可公⽤。消息数据与业务数据同库,占⽤业务系统资源。业务系统在使⽤关系型数据库的情况下,消息服务性能会受到关系型数据库并发性能的局限。
MQ事务消息(最终⼀致性)
⽀持事务消息的MQ,其⽀持事务消息的⽅式采⽤类似于⼆阶段提交。
基于 MQ 的分布式事务⽅案其实是对本地消息表的封装,将本地消息表基于 MQ 内部,其他⽅⾯的协议基本与本地消息表⼀致。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论