常见的分布式事务解决方案

之前梳理了什么是事务;https://blog.csdn.net/u010530712/article/details/84949864

现在来梳理下,分布式事务的解决方案

首先对于分布式事务,一般来说要基于CAP(Consistency :一致性,Availability :可用性,Partition Tolerance:分区容错性)中的两个,要么CP(一致性 + 分区容忍性),要么AP (可用性 +  分区容忍性),理论上是不可能选择CA(一致性+可用性)。

然而,CAP里的Consistency 是强一致性(忽略延迟),但是在实际的应用中,几乎没有系统能完全做到CP(因为总会有那么几毫秒的数据复制延迟在),因此我们追求的是“最终一致性”,即系统中的数据允许经过一定的时间后,最终达到一致的状态,这里的一定时间根据不同的业务需要,时间长短也不同。对于支付类的业务,用户关注,要求秒级别甚至毫秒级别达到一致性,而对于一些发帖子之类的论坛业务,数据复制延迟个10分钟,对于看的用户来说是无感知的。

说完了主要的一致性问题。下面正式介绍几种分布式事务解决方案

2PC(two-phase-commit,二阶段提交)方案

该方案将事务的提交扶持分为两个阶段:准备阶段和提交阶段,事务的发起方叫“协调者”,事务的执行方叫“参与者”

阶段 1:准备阶段

准备阶段有如下三个步骤:

  • 协调者向所有参与者发送事务内容,询问是否可以提交事务,并等待所有参与者答复。

  • 各参与者执行事务操作,将 undo 和 redo 信息记入事务日志中(但不提交事务)。

  • 如参与者执行成功,给协调者反馈 yes,即可以提交;如执行失败,给协调者反馈 no,即不可提交。

阶段 2:提交阶段

如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(rollback)消息;否则,发送提交(commit)消息。

参与者根据协调者的指令执行提交或者回滚操作,注意!是最后释放所有事务处理过程中使用的锁资源(也就是从执行事务开始到协调者给予commit/rollback指令期间,一直是阻塞状态)。

2PC总结

  • 性能问题:所有参与者在事务提交阶段处于同步阻塞状态,占用系统资源,容易导致性能瓶颈。

  • 可靠性问题:如果协调者存在单点故障问题,如果协调者出现故障,参与者将一直处于锁定状态。

  • 数据一致性问题:在阶段 2 中,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。

3PC(three-phase-commit,三阶段提交)方案

三阶段提交相较二阶段提交,引入了超时机制(无论协调者还是参与者,在向对方发送请求后,若长时间未收到回应则做出相应处理)

三阶段将之前二阶段的准备阶段拆成2个阶段(cancommit:确认是否能执行,precommit:执行事务不提交)

阶段 1:canCommit

  • 协调者向所有参与者发出包含事务内容的 canCommit 请求,询问是否可以提交事务,并等待所有参与者答复。

  • 参与者收到 canCommit 请求后,如果认为可以执行事务操作,则反馈 yes 并进入预备状态,否则反馈 no。

阶段 2:preCommit

协调者根据阶段 1 canCommit 参与者的反应情况来决定是否可以进行基于事务的 preCommit 操作,如下表

情况 1

阶段 1 所有参与者均反馈 yes,参与者预执行事务:

  • 协调者向所有参与者发出 preCommit 请求,进入准备阶段。

  • 参与者收到 preCommit 请求后,执行事务操作,将 undo 和 redo 信息记入事务日志中(但不提交事务)。

  • 各参与者向协调者反馈 ack 响应或 no 响应,并等待最终指令。

情况 2

阶段 1 任何一个参与者反馈 no,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务,如上图:

  • 协调者向所有参与者发出 abort 请求。

  • 无论收到协调者发出的 abort 请求,或者在等待协调者请求过程中出现超时,参与者均会中断事务。

阶段 3:do Commit

注意:进入阶段 3 后,无论协调者出现问题,或者协调者与参与者网络出现问题,都会导致参与者无法接收到协调者发出的 do Commit 请求或 abort 请求。此时,参与者都会在等待超时之后,继续执行事务提交。

情况 1:阶段 2 所有参与者均反馈 ack 响应,执行真正的事务提交
  • 如果协调者处于工作状态,则向所有参与者发出 do Commit 请求。

  • 参与者收到 do Commit 请求后,会正式执行事务提交,并释放整个事务期间占用的资源。

  • 各参与者向协调者反馈 ack 完成的消息。

  • 协调者收到所有参与者反馈的 ack 消息后,即完成事务提交。

情况 2:阶段 2 任何一个参与者反馈 no,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务
  • 如果协调者处于工作状态,向所有参与者发出 abort 请求。

  • 参与者使用阶段 1 中的 undo 信息执行回滚操作,并释放整个事务期间占用的资源

  • 各参与者向协调者反馈 ack 完成的消息。

  • 协调者收到所有参与者反馈的 ack 消息后,即完成事务中断。

3PC总结

优点:相比二阶段提交,三阶段提交降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免了协调者单点问题,阶段 3 中协调者出现问题时,参与者会继续提交事务。

缺点:数据不一致问题依然存在,当在参与者收到 preCommit 请求后等待 do commite 指令时,此时如果协调者请求中断事务,而协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致。

 

TCC(try-confirm-cancel)方案

tcc其操作也是分为2个阶段,其中try是第一阶段,confirm、camcel是第二阶段,tcc的整个流程其实可以看成我们编程是的加锁逻辑:

第一阶段

  • Try ,负责资源的检查和预留。(加锁,锁住资源)

第二阶段,根据第一阶段的结果,决定是执行confirm还是cancel

  • Confirm 执行真正的业务。(执行业务,释放锁)

  • Cancel 是预留资源的取消。(出问题,释放锁)

以电商为例,用户购买业务涉及到库存、订单两个服务(不同服务器),需要减库存+创建订单;

现在有库存10,这时用户购买了2份

Try阶段

,

confirm/cancel阶段

TCC总结

TCC 事务机制相对于传统事务机制(X/Open XA),TCC 事务机制相比于上面介绍的 XA 事务机制

优点:

  • 性能提升:具体业务来实现控制资源锁的粒度变小,不会锁定整个资源。 

  • 数据最终一致性:基于 Confirm 和 Cancel 的幂等性,保证事务最终完成确认或者取消,保证数据的一致性。

  • 可靠性:解决了 XA 协议的协调者单点故障问题,由主业务方发起并控制整个业务活动,业务活动管理器也变成多点,引入集群。

缺点: TCC 的 Try、Confirm 和 Cancel 操作功能要按具体业务来实现,业务耦合度较高,提高了开发成本。

MQ 事务方案

MQ事务的方案和ebay提出的本地消息表的理念是很相近的,(本地消息表用MQ来实现),他们的核心思想就是将分布式事务拆成本地事务来处理,利用本地事务的事物特性来保证数据最终一致性。

总的流程如下:服务A基于 MQ 通信通知服务B处理事务,服务B基于 MQ 返回处理结果。

如果服务B消费消息异常,需要不断重试,业务处理逻辑需要保证幂等。

如果是服务B业务上的处理失败,可以通过 MQ 通知服务A进行补偿或者事务回滚

服务A中一般正常流程如图

异常情况:如果出现了断网等

MQ总结

优点是: 

  • 消息数据独立存储 ,降低业务系统与消息系统之间的耦合。

缺点是: 

  • 一次消息发送需要两次网络请求(half 消息 + commit/rollback 消息) 。

  • 业务处理服务需要实现消息状态回查接口。

猜你喜欢

转载自blog.csdn.net/u010530712/article/details/86233426
今日推荐