分布式事务(三)XA、2PC、3PC Diamond

一、@Transactional存在的问题

1、描述:

Spring的事务只是针对一个数据库是有效的,当同一个事务中包含对不同的数据库的操作,就无法保证ACID特性,这时候就考虑分布式事务了。

2、最终实现:

把多个数据库的操作,给包裹在一个事务中,如果任何一个操作报错,多个数据库中的操作全部回滚,如果没有报错,那么多个数据库中的操作全部提交。

二、XA规范:

针对上面的问题,X/Open组织定义了分布式事务的模型,包含多个角色。

  1. AP:Application,应用程序,就是我们的系统应用。
  2. TM:Transaction Manager,事务管理器,专门用来管理系统夸数据库事务的组件。
  3. RM:Resource Manager,资源管理器,就是数据库MySQL。
  4. CRM:Communication Resource Manager,通信资源管理器,消息中间件,但也可以不用。

TM:根据XA定义的接口规范,跟每个数据库进行通信和交互,通知所有数据库,要么一起提交事务,要么一起回滚。

XA:定义好TM与RM之间的接口规范,就是管理分布式事务的那个组件跟各个数据库之间通信的一个接口。
只是一个规范,具体的实现由数据库产商来提供的,比如说MySQL就会提供XA规范的接口函数和类库实现,等等。

三、2PC--Two-Phase-Commitment-Protocol

X/Open组织定义的一套分布式事务的理论模型,2PC就是基于XA规范的协议,来让分布式事务可以落地,定义了实现分布式事务过程中的细节。
image

1、准备阶段:

TM先发送个prepare消息给各个数据库,让各个库先在本地开个事务,然后执行好SQL,这里各个数据库会准备随时提交或者是回滚,对应的事务操作会有对应的日志记录。

各个数据库都返回响应消息给事务管理器,如果都成功了就发送成功的消息,如果失败了就发送失败的消息。

2、提交阶段:

2.1、第一种情况:

TM收到某个数据库的返回消息SQL执行失败。

或者一直无法收到某个数据库的返回消息确认,直接判定这个分布式事务失败,

然后TM通知所有的数据库全部回滚,各个库都回滚好了以后通知TM,TM认为整个分布式事务都回滚了。

2.2、第二种情况:

TM接收到所有的数据库返回的消息都是成功,直接发送个消息通知各个数据库说提交事务。
TM就认为整个分布式事务成功了。

3、2PC存在的问题

image

3.1、同步阻塞:

执行prepare操作会占用公共资源,因为第一阶段不会提交本地事务,直到整个分布式事务完成,才会释放资源。

3.2、单点故障:

TM是个单点,一旦挂掉就完蛋了。

3.3、事务状态丢失:

当前participant的状态只有自己和coordinator知道。

即使把TM做成一个双机热备,一个TM挂了自动选举其他的TM,唯一一个接收到commit消息的数据库也挂了。

新的TM根本不知道这个分布式事务当前的状态,哪个数据库接收到commit,哪个没接收到。

在新的TM启动之前,其他participant就会进入不能rollback和commit的阻塞状态。

3.4、脑裂问题:

如果发生了脑裂问题,就会导致某些数据库没有接收到commit消息,有些库没有收到,就会出现不一致的问题。

四、3PC:

1、3pc的流程如下:

1.1、CanCommit阶段:

TM发送CanCommit消息给各个数据库,然后各个库返回个结果。
这时不会执行实际的SQL语句的就是各个库看看自己网络环境是否ready。

1.2、PreCommit阶段:

如果各个库对CanCommit消息返回的都是成功,就进入PreCommit阶段。
TM发送PreCommit消息给各个库,相当于2PC里的阶段一,执行各个SQL语句,只是不提交;
如果有个库对CanCommit消息返回了失败,TM发送abort消息给各个库,结束这个分布式事务。

1.3、DoCommit阶段:

如果各个库对PreCommit阶段都返回了成功,那么发送DoCommit消息给各个库提交事务。
各个库如果都返回提交成功给TM,那么分布式事务成功;
如果有个库对PreCommit返回的是失败,或者超时一直没返回,那么TM认为分布式事务失败。
直接发abort消息给各个库通知回滚,各个库回滚成功之后通知TM,分布式事务回滚成功。

2、相比2PC的改进点:

2.1、引入了CanCommit阶段。

CanCommit阶段证明了每个数据库都是OK的。

2.2、在DoCommit阶段,各个库有超时机制

如果一个库收到了PreCommit还返回成功了。
超时时间到了,还没收到TM发送的DoCommit消息或者是abort消息,直接判定为TM可能出故障了,然后自己就执行DoCommit操作提交事务。
这样保证资源不会一直被锁定阻塞在这里。

3、3PC的缺陷:

TM在DoCommit阶段发送了abort消息给各个库,结果因为脑裂问题,某个库没接收到abort消息,其他的库提交了事务,还是存在事务不一致问题。

五、全局事务

针对的是X/Open组织定义了一套分布式事务的模型和规范,DTP(Distributed Transaction Processing
Reference Model),分布式事务处理模型,DTP,TM、RM、AP等等角色的这么一套分布式事务的模型。

全局事务,Global Transaction,是DTP模型中的一个概念。指跨多个数据库的分布式事务。

六、JTA事务

其实是J2EE中的一个概念,Java Transaction API,JTA一套分布式事务的编程API,是按照XA、DTP那套模型和规范来搞的,在J2EE中,单库的事务是通过JDBC事务来支持的。

如果是跨多个库的事务,是通过JTA API来支持的,通过JTA API可以协调和管理横跨多个数据库的分布式事务,一般来说会结合JNDI,J2EE里面很多东西定义的很好,但是在业内使用的时候,最近这些年基本没哪个公司用了。

原文地址:https://www.cnblogs.com/huigelaile/p/15780342.html