在单点服务下,Spring整合了@Transactional,通过代理的方法实现事务,基本的事务使用、事务ACID性质、事务失效场景相信各位开发同学都能熟练于心~
但是在分布式环境下呢?@Transactional只能保证单个数据源的数据事务,是不支持分布式事务的。所以在涉及到了多个数据源和分布式服务器时,通常使用分布式事务。
现在常用的分布式事务有:
1.基于XA协议强一致性的 2PC(2阶提交),3PC(3阶提交)
2.基于补偿性事务思想的TCC(try-comfirm-cancel)
3.基于消息队列的分布式事务--RocketMQ
章节一 基本概念
一 、1 XA协议
XA是数据库的分布式事务,强一致性。整个过程分两部分别是准备和提交,在整个过程中,TM会锁住数据库资源,存在长事务风险。
XA协议中的三个模型:
1.AP:应用程序Application,业务层。
2.TM:事务协调者Transaction Manager,事务调度的核心。
3.RM:资源管理器Resource Manager,数据库。

章节二 分布式事务实现
二 、1 2PC
简介:
2PC就是二阶提交,并且引入了事务协调者TM和参与者RM两个角色。
XA协议的2PC分别指的是准备和提交。
在Java中可以用atomikos集成实现2PC。
流程图:

如流程图所示,2PC第一阶段会直接操作并锁定数据库资源,直到所有的分布式系统操作执行完,告诉TM执行情况;第二阶段根据执行情况进行提交/回滚。
缺点分析:
看完2PC的流程后,经验老道的开发应该就发现问题,这个解决方案存在许多漏洞,并不能保证CAP中的AP。让我们来一一分析2PC的不足。
1.性能问题:
2PC(XA协议)遵循强一致性,只有当所有结点准备完毕后才会提交/回滚,释放资源。
2.协调者单点故障:
事务协调者是模型的核心,假如协调者挂了,参与者收不到提交/回滚,整个事务就锁定在中间状态,无法释放资源。
3.数据不一致问题:
假如在第二阶段的过程中,出现网络问题,一部分参与者收到提交/回滚指令,另一部分没有收到,就会出现结点不一致。
二 、2 3PC
简介:
XA三阶段提交在2PC的基础上增加了询问是否能提交(cancommit),并且引入超时机制。如果参与方RM迟迟没收到TM事务协调者的提交/回滚指令,会自动进行提交。解决了协调者单点故障问题,改善了性能问题(性能有所提升),但是依旧无法根除性能问题和数据不一致问题。
3PC相当于是对于2PC做了一些努力,但是效果甚微。
流程图:

如流程图所示3PC有三个阶段,分别是CanCommit、PreCommit、DoCommit。该算法不会上来就直接操作资源,而是有一个询问的操作,从而防止某些资源不可用时所有参与者都阻塞。
缺点分析:
1.增加了项目复杂度
2.性能问题
3.数据不一致问题
二 、3 TCC
简介:
TCC也是一个重要的分布式事务实现模型,在2PC和3PC中都是数据库层面的,而在TCC可以是业务层面的分布式事务,使用范围场景比较多。
TCC是基于补偿思想的实现最终一致性,TCC指的是try-confirm-cancel。
1.try:预留资源
2.confirm:确定提交,把预留资源提交
3.cancel:取消提交,释放预留资源
流程图:
缺点分析:
1.开发量大,需要提供三个接口
2.取消和撤回需要保证操作幂等性
二 、4 消息事务
简介:
RocketMQ原生方法消息事务可以支持分布式事务。
流程图:

1.producer发送half给broker(消息中间件),此时消费者并不能感知。
2.当broker接受成功后,告知producer,执行本地事务。
3.根据本地事务执行情况,告诉broker是否丢弃消息(commit/rollback)
4.如果是commit,推送给消费者。
5.消费者执行完事务后,消费消息。(broker有重试机制,重试直到成功,重试一定次数后把数据死信队列,由人工处理即可)
缺点分析:
1.基于消息队列实现,事务不能马上执行,有时间延时性。
章节三 总结
综合分析,不同的分布式解决方案有不同的优缺点,大家可以针对不同场景做事务实现。
1.基于XA协议的2PC和3PC是一种强一致性的事务(体现在锁表),不过还是会有数据不一致,阻塞,而且只适用于分布式数据库层面。
2.基于补充机制的TCC适用范围更广,但代码复杂度增加。
3.基于RocketMq的消息事务适用于时间敏感性不高的业务。




