分布式事务2PC、3PC、TCC、RocketMQ事务消息方案详解与对比(详细图解)

这篇文章将介绍分布式事务中的多种实现方案,及各种分布式事务方案的实现原理、事务执行过程、优缺点,读完这篇文章相信你会对2PC、3PC、TCC、MQ事务消息有个详细的了解

分布式事务的处理方法有哪些?

XA协议:基于分布式事务协议,主要由事务管理器和本地资源管理器组成,事务管理器是一个全局调度者,负责本地资源管理器统一的提交或回滚事务。mysql、oracle均已支持XA协议

2PC(两阶段提交)

在这里插入图片描述

基本流程:

  1. Prepare预备阶段:预执行需要执行的sql,但不提交事务
  2. Commit提交阶段:提交事务

不足:

  1. 数据不一致:在事务管理器向所有服务发送提交事务Commit阶段时,某些参与者可能发生网络抖动,无法正常接收到Commit请求,从而导致每个参与者的数据不一致
  2. 超时导致同步阻塞:当有一个参与者出现通信超时,其余所有参与者将一直阻塞无法释放资源
  3. 单点故障风险:如图可知,资源管理器统一协调所有参与者,一旦资源管理器出现故障,则参与者无法完成Commit操作,会一直处于阻塞状态。尽管资源管理器会重新选举,当还是无法解决之前遗留的阻塞问题。
  4. 性能问题:所有参与者在事务提交阶段处于同步阻塞状态,占用系统资源,容易导致性能瓶颈

3PC(三阶段提交)

在这里插入图片描述

基本流程:

  1. CanCommit:协调者向所有参与者发送CanCommit命令,,询问是否可以执行事务提交操作。如果全部响应YES则进入下一个阶段
  2. PreCommit:预提交事务操作,询问是否可以进行事务的预提交操作,参与者接收到PreCommit请求后,如参与者成功的执行了事务操作,则返回Yes响应,进入最终commit阶段。一旦参与者中有向协调者发送了No响应,或因网络造成超时,协调者没有接到参与者的响应,协调者向所有参与者发送abort请求,参与者接受abort命令执行事务的中断。
  3. DoCommit:前两个阶段都返回YES响应后,协调者向参与者发送DoCommit正式提交事务命令,如果没有接收到ACK响应,则向其它参与者发送abort命令,执行事务中断

相对于2PC的改进:

  1. 在协调者与参与者加入了超时机制,当在一定时间内未收到协调者的commit请求,会自动提交事务,不会一致阻塞等待
  2. 3PC将2PC的Prepare准备阶段拆分为 2 个阶段,插入了一个 ==PreCommit ==阶段,解决原先在2PC中,由于协调者发生故障而导致参与者无法知晓是否commit或abort的状态而产生的相当长的阻塞问题得以解决
  3. 有了自动提交事务,一旦发生单点故障,事务也可以自动提交

不足:

  1. 在发送abort命令的时候,如果因为网络原因部分参与者没有接收到请求,还是会导致数据不一致性问题

TCC(事务补偿)

TCC也是实现分布式事务的一种方案,不过它是属于应用层面的,非基于XA协议,需要我们编写业务代码来实现类似于2PC的命令功能
核心思想
对于每一个操作都有其对应的确认(Confirm)和补偿(Cancel)方法,且它们是幂等性的

在这里插入图片描述

基本流程:

  1. Try:通过Try操作来检查、预留需要的库存,比如需要2台iphone12并进行冻结
  2. Confirm:真正执行业务操作,在之前预留的资源基础上完成购买和创建订单
  3. Cancel:在Try阶段预留2台iphone12失败,则取消所有业务资源的预留(也就是恢复try之前)

优点:

  1. 性能提升:依据业务来控制资源锁的粒度,不会控制整个资源
  2. 数据最终一致性:基于Confirm和Cancel的幂等性,能够保证事务完成或取消
  3. 可靠性:解决了XA协议中事务管理器单点故障问题,直接由业务活动发起并控制整个业务活动,业务活动管理器也变成了多点(集群)

不足:
7. 代码侵入性强:之前也说需要在业务层面实现这三个命令,实际就是需要实现三个接口
8. 开发成本高:因为需要自己实现三个阶段的业务代码,开发量很大;且如果要保证数据一致性,需要自己实现幂等性

RocketMQ事务消息(最终一致性)

在这里插入图片描述

基本流程:

  1. 事务主动方向消息集群发送消息,但这个消息不能被消费
  2. 事务主动方执行本地事务A,执行成功后根据消息地址去修改消息状态为commit或rollback,如果是commit则会被事务被动方消费,否则将删除消息
  3. 事务被动方读取消息,然后执行本地事务B
  4. 事务被动方将事务B执行结果返回到MQ Server
  5. 事务主动方读取接收方事务处理结果
异常情况1:如果事务主动方发送commit or rollback消息失败,未到达消息集群
  1. 消息集群(MQ Server)会发起消息回查
  2. 事务主动方收到回查消息后,会检查本地事务的执行结果
  3. 根据本地事务的执行结果重新发送commit or rollback消息
  4. MQ Server根据接收到的消息(commit or rollback)判断消息是否可消费或直接删除
异常情况2:接收方消费失败或消费超时

一直重试消费,直到事务被动方消费消息成功,整个过程可能会导致重复消费问题,所以业务逻辑需要保证幂等性

异常情况3:消息已消费,但接收方业务处理失败

通过MQ Server通知发送方进行补偿或事务回滚

优点:

  1. 系统解耦:消息之间独立存储,系统之间消息完成事务
  2. 复杂度低,实现简单

缺点:

  1. 一次消息需要发送两次请求(half消息+commit or rollback)
  2. 业务中需要实现消息状态回查接口
Spring中已经有了事务,还需要使用事务消息吗?

如果是在Spring框架下,可以将发送消息的逻辑绑定到本地事务中,发消息失败就抛出异常,回滚事务,以此来保证本地事务与发送消息的原子性

参考

  • 分布式事务各大方案详细解读2PC、3PC、TCC、本地消息表、MQ事务、Saga

https://blog.csdn.net/qq_32828253/article/details/109956240

你可能感兴趣的:(分布式事务2PC、3PC、TCC、RocketMQ事务消息方案详解与对比(详细图解))