工欲善其事必先利其器,既然咱们决定要作一个分布式事务框架,那首先须要了解一下,分布式事务是怎么回事,它跟传统的本地事务有什么区别,解决方案有哪些,每种解决方案的对比等等。mysql
在了解分布式事务以前,先回顾一下本地事务,顾名思义,本地事务就是在同一个JVM中,一个开启了事务的业务方法就是本地事务。而这一个开启了事务的业务方法里面的操做要么所有执行成功,要么所有执行失败,不容许只成功一半另一半执行失败的事情发生。例如该业务方法中,有两次数据库更新操做,那么这两次数据库操做要么所有执行成功,要么所有回滚。使用专业术语来说的话,就是事务的4个基本特性:Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durablity(持久性),统称ACID,这里简单的对ACID作一个概念的说明,看成是作个笔记:sql
经过以上的回顾咱们知道,本地事务对于咱们来讲不是什么问题,由于咱们能够直接使用数据库的事务支持,好比mysql、oracle这些数据库对事务都有很好的支持。可是,对于分布式应用来讲的话,事务就没有那么简单了,由于须要开启事务的业务方法,极可能是分布在不一样应用程序中,这就说明,你们不在同一个JVM中,事务空间都不同了,那就没办法作到要么所有执行成功,要么所有执行失败了,咱们能够看如下分析图:数据库
如上图所示:这是一个分布式应用,完成一个付款业务的操做须要有4个微服务参与,你们都独立运行在本身的JVM中,其中,订单系统、商品系统和会员系统是服务提供者,有本身对应的数据库。
客户端应用在发起了付款请求时,调用了订单系统的支付业务makePayment,而makePayment方法中,又调用了远程商品系统的decrease方法和远程会员系统的payment方法,分别作减库存和扣余额的操做,那如今就有两种状况了:
第一种状况是流程正常执行,各个业务参与者都没有异常,万事大吉。
第二种状况是其中有一个业务参与者出现异常了,按照咱们上面对本地事务的理解,它们应该要作到要么所有执行成功,要么所有执行失败了,这样才能确保数据一致性。但如今这个不是单体应用,而是分布式应用,本来一个本地逻辑执行单元被拆分到了多个独立的微服务中,这些微服务又分别操做不一样的数据库和表,服务之间经过网络调用。因此这就没办法确保要么所有执行成功,要么所有执行失败了,由于我怎么知道远程的服务是否执行成功呢。
因此,如今的问题就出现了,咱们不能再用单体应用的那种事务方式,套用在分布式应用中了,必需要思考用什么样的解决方案来控制分布式应用的事务问题。这就是“分布式事务”。安全
分布式事务的解决方案有不少,但能够具体概括为两种:网络
XA是一个分布式事务协议,XA中大体分为两部分:事务管理器和本地资源管理器。其中本地资源管理器每每由数据库实现,好比Oracle、DB2这些商业数据库都实现了XA接口,MySQL5.7以后也支持XA分布式事务。而事务管理器做为全局的调度者,负责各个本地资源的提交和回滚。
XA分布式事务协议的工做原理是:把各个微服务中的本地资源交给一个统一的事务管理器管理,事务管理器能够看作是事务协调者的角色(coordinator),各个本地资源管理器能够看作是事务参与者的角色(partcipant)。各个事务参与者之间不能直接通信,而是经过事务协调者间接通信,通俗来讲,服务A怎么知道服务B是否执行成功?就是由事务协调者转告各个事务参与者了。经过如下分析图,看看XA实现分布式事务的流程:架构
以上就是XA分布式事务执行流程,加入了全局的事务管理器做为协调者,在接收到发起带事务的业务方法后,发送prepare到各个事务参与者,各个事务参与者接收到prepare后,开启本地事务being,并执行本地业务流程,若是流程正常运行,则返回ready结果给事务协调者,告知准备就绪了,这时,若是各个事务参与者返回的结果都是ready,那么事务协调者就会再次发送一个全局事务提交global_commit的消息到各个事务参与者,最后,各个事务参与者受到global_commit后,提交本地事务commit。
这是业务流程正常执行的状况,那若是由于流程有异常就走以下流程:事务协调者仍是发送prepare到各个事务参与者,事务参与者接收到prepare后,开启本地事务begin,接着执行业务流程,此时,若是有某个事务参与者执行业务报错,返回异常abort给事务协调者,事务协调者会再次发送全局回滚global_rollback给各个事务参与者,事务参与者接受到global_rollback后,开始回滚本地事务rollback,即使是流程正常执行的也要回滚掉,这样就能确保要么一块儿成功,要么一块儿失败。
总的来讲,XA协议比较简单,并且一旦商业数据库实现了XA协议,使用分布式事务的成本也比较低。可是,XA也有致命的缺点,那就是性能不理想,特别是在并发量很高的状况下,会带来性能瓶颈,由于根据以上执行流程图的分析可知,在全局事务管理器向各个事务参与者发送prepare时,是须要锁住资源的,也就是此时,全部相关连的微服务都处于阻塞状态,须要等到全部事务参与者返回最终处理结构,才能释放锁,因此XA没法知足高并发场景。其次,XA目前在数据库的支持上不太理想,mysql5.7以前是不支持的,而且还有许多nosql也没有支持XA,而大多数新型的互联网微服务应用都会使用各类nosql数据库,因此这就致使了XA的应用场景变得很是狭隘。并发
TCC是Try-Confirm-Cancel的简称。其核心思想是:每一个须要开启分布式事务的业务方法,都要注册一个与其对应的检测、确认和撤销的操做,以下:oracle
Try阶段:主要是对业务系统作检测的操做,没有问题就调用确认操做,有问题则调用取消操做。框架
Confirm阶段:确认执行业务操做。异步
Cancel阶段:取消执行业务操做。
具体执行流程以下:
经过以上的流程,咱们能够发现,TCC的分布式事务处理与XA的分布式事务处理流程是很是类似的, 调用try接口检查业务是否有异常的操做,相似于XA的prepare预提交,若是接口返回正常,则调用confirm确认执行业务,操做数据。
那若是其中有一个事务参与者在调用了try接口检测后,返回了异常给事务协调者,可是以前极可能已经有其余事务参与者调用了confirm接口,执行业务流程操做了数据,那这时,事务协调者就须要调用事务参与者的cancel接口,撤销以前修改的数据,达到相似回滚的效果。
不过XA是在跨库的DB层面,而TCC是应用层面,须要经过业务逻辑来实现分布式事务。TCC的实现方式优点在于:没有项目XA协议那样,把分布的资源统一管理,这就使得分布的资源不会被加锁,从而提升总体的吞吐量,因此这种分布式事务的解决方案,在性能和吞吐量要求高的应用使用的仍是比较多的。而不足之处则在于对应用的侵入性很是强,业务逻辑的每一个分支都须要实现try、confirm、cancel三个操做。此外,其实现难度也比较大,须要按照网络状态、系统故障等不一样的失败缘由实现不一样的回滚策略。同时,confirm和cancel接口还要考虑幂等性的问题,由于confirm和cancel有可能会被屡次调用。
可靠消息事务全称叫作可靠消息事务最终一致性,它一般没有像前面两种分布式事务解决方案那样有回滚或撤销数据的操做,而更多的是强调事务的补偿和重试。这里的可靠消息指的是消息队列中间件,消息队列其中一个特色就是消息可靠性,而该解决方案最终能达到事务一致,依靠的核心就是消息队列。先粗略的看看它执行流程:
从以上的执行流程能够发现,各个事务参与者都是相对独立的,无论在执行业务方法的过程当中是否有异常,总体的业务流程都要先跑完,这个是该解决方案的前提。而后在调用事务参与者的业务方法的同时,往消息队列发送事务相关的消息,这样的话,出现异常的事务参与者再从消息队列中获取消息,从新执行本地的业务,达到补偿和重试的效果,整个事务中,无论中间有哪些参与者出错,可是最终仍是事务一致的。
这种解决方案是全部解决方案中最柔性的,而且灵活度很是高,能够根据本身具体的业务场景作改变,同时,对比TCC来讲,性能和吞吐量更高,而且对应用的侵入性更低。性能的提升体如今:没有了业务检测的环节,跟本来同样,该怎么调用远程方法就怎么调用,只是增长了一个往MQ发送消息的操做,可是该操做是异步的,并且MQ也是具有高吞吐量的特性。而侵入性更低体如今:MQ是中间件,只须要经过网络来调用便可,咱们的业务方法并不会因为分布式事务解决方案的加入而有太多的改造,加入的代码更可能是之外围扩展,或者组件的方式加入。
可靠消息事务最终一致性的解决方案优势很明显,但缺点也不是没有的,首先该解决方案设计过于复杂,组件不少,须要考虑的状况繁杂,实现起来比较困难。其次,虽然它是最柔性,最灵活和性能最高的,可是事务的原子性和一致性是最弱的,由于这种解决方案是以你们都不出错为前提的,若是其中有一个出错,本身经过补偿机制从新执行本地事务,但重试的过程自己就是不肯定性的,好比说:A转钱给B,A帐户扣钱了,可是B帐户加钱时出错,在该机制下,A帐户不会回滚,而是让B帐户从新尝试加钱,那这就产生时间上的延迟了,极可能等了好久,都没见B帐户把钱加上去,或者不断重试都是失败的,最终致使整个事务不一致,须要人工处理。
总的来讲,可靠消息事务最终一致性因为它的事务原子性和一致性比较弱,因此决定了它在一些事务ACID要求很是强的应用中是不能使用的,不然会形成不少安全性的问题,可是对于大多数互联网应用来讲,都是一个不错的解决方案。而具体使用哪种,仍是取决于项目的业务场景,而后作全面的对比、考量和取舍。
感兴趣的能够本身来个人Java架构群,能够获取免费的学习资料,群号:855801563对Java技术,架构技术感兴趣的同窗,欢迎加群,一块儿学习,相互讨论。