美文网首页中间件
分布式事务2PC、3PC、TCC、RocketMQ事务消息方案详

分布式事务2PC、3PC、TCC、RocketMQ事务消息方案详

作者: Zal哥哥 | 来源:发表于2021-10-18 16:16 被阅读0次

    这篇文章将介绍分布式事务中的多种实现方案,及各种分布式事务方案的实现原理、事务执行过程、优缺点,读完这篇文章相信你会对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. <mark style="box-sizing: border-box; outline: 0px; background-color: rgb(248, 248, 64); color: rgb(0, 0, 0); overflow-wrap: break-word;">在协调者与参与者加入了超时机制</mark>,当在一定时间内未收到协调者的commit请求,会自动提交事务,不会一致阻塞等待
    2. 3PC将2PC的Prepare准备阶段拆分为 2 个阶段,插入了一个 ==PreCommit ==阶段,解决原先在2PC中,由于协调者发生故障而导致参与者无法知晓是否commit或abort的状态而产生的相当长的阻塞问题得以解决
    3. 有了自动提交事务,一旦发生单点故障,事务也可以自动提交

    不足:

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

    TCC(事务补偿)

    TCC也是实现分布式事务的一种方案,不过它是属于应用层面的,非基于XA协议,需要我们编写业务代码来实现类似于2PC的命令功能
    核心思想
    <mark style="box-sizing: border-box; outline: 0px; background-color: rgb(248, 248, 64); color: rgb(0, 0, 0); overflow-wrap: break-word;">对于每一个操作都有其对应的确认(Confirm)和补偿(Cancel)方法,且它们是幂等性的</mark>

    在这里插入图片描述

    基本流程:

    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:接收方消费失败或消费超时

    一直<mark style="box-sizing: border-box; outline: 0px; background-color: rgb(248, 248, 64); color: rgb(0, 0, 0); overflow-wrap: break-word;">重试消费</mark>,直到事务被动方消费消息成功,整个过程可能会导致重复消费问题,所以业务逻辑需要保证幂等性

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

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

    优点:

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

    缺点:

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

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

    参考

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

    相关文章

      网友评论

        本文标题:分布式事务2PC、3PC、TCC、RocketMQ事务消息方案详

        本文链接:https://www.haomeiwen.com/subject/metwoktx.html