一文带你系统性读懂分布式事务的解决方案以及分布式事务协议

缘起

笔者最近在看分布式事务的时候发现网上很多资料很零散,不够系统,看的云里雾里,比如在分布式事务中的关键词

  1. DTP模型
  2. TCC
  3. XA规范
  4. 两阶段型
  5. 三阶段型
  6. JTA
  7. 基于可靠消息服务的分布式事务
  8. 异步确保型
  9. 补偿型
  10. 最大努力通知型
  11. 定期校对
  12. sagas事务模型

这么多关键词是什么意思?之间又有什么关系??

系统性的了解分布式事务协议和解决方案

什么是协议和解决方案

先说说什么是协议,
协议就是约定,就是提出来这个东西应该怎么做的约定,不是一个具体的解决方案,比如大家约定了2.5寸的硬盘的接口是怎样的,长宽高是多少,但是具体你硬盘怎么做是你的事,你可以用塑料做,也可以做铁做,也可以用木头做。
而解决方案就是具体的做法,比如上面说的硬盘用什么材料做,在技术中往往就是说具体的框架。

分布式事务的协议

目前比较常用的分布式事务解决方案的协议有两种

  1. 强一致的X/Open DTP模型
  2. 弱一致的TCC

在说这两个之前简单提一嘴XA规范

XA 就是 X/Open DTP 定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。 XA 接口函数由数据库厂商提供。 

X/Open DTP模型

X/Open 组织(即现在的 Open Group )定义了分布式事务处理模型。 X/Open DTP 模型( 1994 )包括应用程序( AP )、事务管理器( TM )、资源管理器( RM )、通信资源管理器( CRM )四部分。一般,常见的事务管理器( TM )是交易中间件,常见的资源管理器( RM )是数据库,常见的通信资源管理器( CRM )是消息中间件。 通常把一个数据库内部的事务处理,如对多个表的操作,作为本地事务看待。数据库的事务处理对象是本地事务,而分布式事务处理的对象是全局事务。 所谓全局事务,是指分布式事务处理环境中,多个数据库可能需要共同完成一个工作,这个工作即是一个全局事务,例如,一个事务中可能更新几个不同的数据库。对数据库的操作发生在系统的各处但必须全部被提交或回滚。此时一个数据库对自己内部所做操作的提交不仅依赖本身操作是否成功,还要依赖与全局事务相关的其它数据库的操作是否成功,如果任一数据库的任一操作失败,则参与此事务的所有数据库所做的所有操作都必须回滚。 一般情况下,某一数据库无法知道其它数据库在做什么,因此,在一个 DTP 环境中,交易中间件是必需的,由它通知和协调相关数据库的提交或回滚。而一个数据库只将其自己所做的操作(可恢复)影射到全局事务中。

二阶段和三阶段

根据X/Open DTO模型这一思想又衍生出二阶段提交和三阶段提交
2PC: 二阶段提交(Two-phaseCommit)是指,在计算机网络以及数据库领域内,为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的一种算法(Algorithm)。通常,二阶段提交也被称为是一种协议(Protocol))。在分布式系统中,每个节点虽然可以知晓自己的操作时成功或者失败,却无法知道其他节点的操作的成功或失败。当一个事务跨越多个节点时,为了保持事务的ACID特性,需要引入一个作为协调者的组件来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交(比如将更新后的数据写入磁盘等等)。因此,二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。所谓的两个阶段是指:第一阶段:准备阶段(投票阶段)和第二阶段:提交阶段(执行阶段)。

说人话就是:你第一阶段询问你的三个朋友,我们去钓鱼 大保健啊?(询问),你三个朋友都说OK呀 没问题啊(预提交),然后你看到大家都很赞同,你就喊大家出来大保健(提交),大家就去了。如果第一阶段三个朋友任何一个回复你说他去不了或者他没有回复你是去还是不去,那么你就会告诉你所有的朋友,本次大保健活动取消(回滚)。
这里有个问题就是第二阶段你你告诉你朋友,那我们去大保健吧,结果有一个哥们因为网络原因没收到你的通知,他也不知道第一阶段其他两个朋友到底是去还是不去,那么他自己就不知道去还是不去,就会一直在那等你的去还是不去的通知(堵塞),也有可能他等的时间久了他就没去,但是其他两个收到你消息的哥们就去了,那么就会造成数据不一致性问题。

3PC: 三阶段提交(Three-phase commit),也叫三阶段提交协议(Three-phase commit protocol),是二阶段提交(2PC)的改进版本。与两阶段提交不同的是,三阶段提交有两个改动点。

  1. 引入超时机制。同时在协调者和参与者中都引入超时机制。
  2. 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
    也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。

说人话就是:你第一阶段询问你的三个朋友,我们去钓鱼 大保健啊?(询问),你三个朋友都说OK呀 没问题啊(CanCommit),第二阶段,你看到大家都很赞同,你就告诉你那几个朋友,大家都说没问题,我们准备下就去吧(PreCommit),第三阶段,你就喊大家出来大保健,大家就去了(DoCommit)。如果第一阶段或者第二阶段三个朋友任何一个回复你说他去不了或者他没有回复你是去还是不去,那么你就会告诉你所有的朋友,本次大保健活动取消(回滚)。
相比较二阶段提交,此处新增了一个阶段就是你会告诉你的朋友,大家都觉得没问题这个阶段,这样的话,即使出现你你告诉你朋友,那我们去大保健吧,结果有一个哥们因为网络原因没收到你的通知,他是知道第一阶段其他两个朋友到底是去还是不去的,那么他自己就不知道去还是不去,就不会堵塞,但依然有可能第三阶段你告诉大家的是本次活动取消,但有吊毛没收到请求,那么他自己一个人傻乎乎的去了,其他几个收到了的又没去,所以还是会有数据一致性问题。只是相比较于二阶段,三阶段减少了数据一致性问题出现的概率,因为某个吊毛虽然没收到DoCommit的请求,但是他肯定是收到了PreCommit的请求的,那么他就会觉得,大家都说好了去,大概率是会去的。

X/Open DTP模型的实现框架

前面说的都是理论,那么基于这些理论,在java中又有具体的实现框架,主要有

  1. JOTM(java open transaction manage)
  2. Atomikos,在JavaEE平台下,WebLogic、WebShare等主流商用的应用服务器提供了JTA的实现和支持。在Tomcat下是没有实现的,这就需要借助第三方的框架,如:Jotm,Automikos.关于DTP的详细说明和在项目中使用DTP的实战。其中spring对Automikos有很好的集成(JTA)。

视频
让技术不再生涩难懂 - Spring+事务,原理就是这么简单(主要讲解了Spring中使用Automikos来实现JTA事务)

TCC(柔性事务,最终一致)

简单来说TCC也有点像2PC。只是TCC位于业务服务层而非资源层 TCC没有单独的准备(Prepare)阶段,Try操作兼备资源操作与准备能力 • Try操作可以灵活选择业务资源的锁定粒度(以业务定粒度) TCC有较高开发成本,因为你还要开发很多补偿性的接口。比如原来你只有一个金额加的接口,你现在可能需要开发一个金额减的接口以备补偿的时候使用。但现在企业最不缺的就是程序员,故大多企业使用这种方式实现。TCC 分布式事务框架 ByteTCC、Himly、TCC-transaction。简单来说这些框架可以很方便的帮你实现TCC。比如你可以在方法上加个注解来说明方法失败后调用此方法方法进行回滚。用通俗易懂的方式讲解了TCC和基于可靠消息服务的分布式事务。

TCC事务又有以下几种实现方案

  1. 最大努力通知(定期校对)(最终一致):如果你做过支付系统的话,就会知道我们接支付宝,微信支付的时候有个场景是需要定期去查询 支付宝,微信主动查询支付状态的,这就是定期校对。
  2. 基于于可靠消息服务的分布式事务(最终一致):大体来说就是比如订单系统在订单提交后需要把发货这个消息发送给物流系统,而只要订单系统保证这个消息能100%发送到MQ,物流系统能100%消费掉这个消息,就能实现分布式事务的最终一致性。与TCC类似,只是这个更适合异步的场景。

TCC的实现框架

那么基于上面的解决方案又有具体的实现框架

  1. Himly
  2. TCC-transaction

视频
分布式系统开发实战篇 - TCC分布式事务实现(主要演示了TTC事务的两个框架Himly、TCC-transaction,以及讲了一些分布式事务的基础知识)

饿了么外卖场景,分布式事务解决方案实录(讲解了分布式事务的基本概念和分布式事务中基于可靠消息MQ的解决方案)

你可能感兴趣的:(面试专栏)