#1 系列目录java
#2 X/Open DTPmysql
DTP全称是Distributed Transaction Process,即分布式事务模型。以前咱们接触的事务都是针对单个数据库的操做,若是涉及多个数据库的操做,还想保证原子性,这就须要使用分布式事务了。而X/Open DTP就是一种分布式事务处理模型。web
##2.1 X/Open DTP模型sql
X/Open是一个组织,维基百科上这样说明:数据库
X/Open是1984年由多个公司联合建立的一个用于定义和推动信息技术领域开放标准的公司tomcat
上述组织就针对分布式事务提出了一个模型,即DTP模型(Distributed Transaction Process),该模型以下所示:服务器
上面主要涉及了三个对象:app
AP(Application Program):应用程序框架
TM(Transaction Manager):事务管理器分布式
负责协调和管理事务,它和以前说的Spring的事务管理器PlatformTransactionManager可不同。
RM(Resource Manager):资源管理器
能够理解为数据库或者JMS。
他们三者的关系:
更多的规范内容,能够参见Distributed Transaction Processing:The XA Specification
##2.2 两阶段提交
全称是The two-phase commit protocol,简称2PC
当须要协调多个资源管理器进行分布式事务的时候,就须要使用到两阶段提交协议,以下图所示:
第一个阶段:事务管理器经过XA协议,向资源管理器发送prepare命令,询问他们预提交是否成功,每一个资源管理器给出本身的响应,预提交成功或者失败
第二个阶段:根据第一个阶段的资源管理器的回复状况,若是所有表示预提交成功,则事务管理器向全部的资源管理器发送最终的提交命令。若是有一个资源管理器回复预提交失败,则事务管理器向全部的资源管理器发送回滚命令,所有进行回滚
经过这样的两阶段提交协议,便可完成了分布式事务的功能。这样的协议的正是基于了事务管理器和资源管理器的双向通讯能力,而这在以前的本地事务中,如jdbc事务中,咱们只能经过Connection向数据库传递命令,不能从数据库获取事务的一些执行信息,这种状况是单向的。
然而仍是存在一些问题的:
两阶段提交协议是阻塞式协议,因此事务管理器必须等待每个资源管理器发送回复以后,才能进行下一步操做。一旦资源管理器挂掉,事务管理器则收不到响应,就会形成事务管理器一直等待。这时候就必须引入超时机制,一旦超过某个时间尚未回复,则认为失败,回滚全部操做,这些都是很是耗性能的。
一旦事务管理器挂掉,则资源管理器则一直等待事务管理器的命令。这时候可能就须要使用备份的事务管理器来接替原来的事务管理器的工做
更多资料与问题,见以下:
上述接口规范不是针对某种语言的,java是如何来落实上述规范的呢?这就是JTA的内容了。先来预览下JTA的包结构:
主要2个大包的内容:
##3.1 AP、TM、RM三大对象
下面来详细说明:
TM:即javax.transaction.TransactionManager,整体接口定义以下:
定义了一些经常使用的事务操做,这里操做的事务的定义为javax.transaction.Transaction,接口以下所示:
RM:资源管理器,与它通讯的表明就是javax.transaction.xa.XAResource,资源管理器的一个通讯表明,咱们经过XAResource与资源管理器器来通讯。因此XAResource的实现类实现了两阶段提交协议,接口内容以下:
咱们看到有一个Xid接口:X/Open组织规定了,对于每一个分布式事务,都有一个对应的惟一标示。这个惟一标示在java中就是Xid接口,该接口文档以下:
The Xid interface is a Java mapping of the X/Open transaction identifier XID structure The Xid interface is used by the transaction manager and the resource managers This interface is not visible to the application programs
接下来看下XAResource的其余方法
下面看一个简单模拟两阶段提交的例子,加深对上面的方法的理解:
xaRes1.start(xid, XAResource.TMNOFLAGS); stmt1.executeUpdate("insert into test_table1 values (100)"); xaRes1.end(xid, XAResource.TMSUCCESS); stmt1.executeUpdate("insert into test_table1 values (99)"); xaRes2.start(xid, XAResource.TMNOFLAGS); stmt2.executeUpdate("insert into test_table2 values (100)"); xaRes2.end(xid, XAResource.TMSUCCESS); ret1 = xaRes1.prepare(xid); ret2 = xaRes2.prepare(xid); if (ret1 == XAResource.XA_OK && ret2 == XAResource.XA_OK) { xaRes1.commit(xid, false); xaRes2.commit(xid, false); }else{ xaRes1.rollback(xid); xaRes2.rollback(xid); }
过程说明:
首先使用start、end来告知资源管理器分布式事务的边界,上述stmt1.executeUpdate("insert into test_table1 values (99)");没有在start、end范围以内,则不会划入分布式事务的管辖中,而是做为了通常的本地事务。
而后遍历每一个资源管理器的通讯表明,使他们询问资源管理器预提交的状况
若是所有OK则所有提交,不然所有回滚
更多的例子,能够参考这里JAVA分布式事务原理及应用
##3.2 UserTransaction接口
UserTransaction接口是给开发人员使用的事务接口,屏蔽了底层的实现细节,经过该接口就能够操做一个分布式事务。该接口的实现一般是委托给TM即事务管理器来完成。接口内容以下:
能够看到,UserTransaction的这些方法在TM即事务管理器中都有对应的方法。
##3.3 JTA中涉及的角色
涉及到哪些角色呢?他们的职责与任务分别什么呢?
开发人员:只需经过使用UserTransaction接口来进行操做分布式事务
TransactionManager的实现提供者:实现UserTransaction、TransactionManager、Transaction接口,经过与XAResource接口交互来实现分布式事务,TransactionManager的实现提供者如jotm、Atomikos,他们的上述接口分别以下
XAResource接口的实现者:须要由资源管理器者来实现,若资源管理器是数据库,则数据库须要提供XAResource接口的实现。如对于mysql来讲,对应的实现为 com.mysql.jdbc.jdbc2.optional.MysqlXAConnection。这种形式下的数据库驱动就是支持分布式事务的数据库驱动
更多的支持分布式的数据库驱动能够看下这里XA Drivers
##3.4 JTS
JTS是什么呢?它和JTA是什么关系呢?
这个我也是没弄清楚,能够参考这里的说法,若是以为不对,自行去深刻研究下,原文在这里JTA、JTS各司其职,共职分布式事务。
JTS也定义了一套规范,它约定了各个程序角色之间如何传递事务上下文,它源自CORBA 的OTS规范,基于IIOP(一种软件交互协议)。不要认为JTS是JTA的实现,JTA其实就定义了一个空架子,告诉JTA的实现者应该怎样作怎样作,可是具体到作的时候JTS就来插一手了。由于JTA约定的这些角色要进行事务上下文的交互啊,JTS约定了应该怎样去进行交互
##3.5 疑问解答
1 是否是数据库驱动必需要支持XA协议,即支持分布式事务?
不是,可使用第三方框架如jotm、Atomikos来模拟XA协议
2 使用分布式事务,是否是必定要应用服务器的支持?
不是。
jboss是支持的,因此咱们能够直接使用jboss本身实现的UserTransaction来实现分布式事务(使用JNDI方式,这时候要求数据库驱动支持XA协议),能够不须要像jotm、Atomikos等第三方框架
tomcat就是不支持的,可是咱们可使用第三方框架来实现,如jotm、Atomikos
#4 结束语
这一篇这要了解了分布式事务的一些概念与JTA的接口定义,下一步就开始深刻源码分析jotm、Atomikos是如何来实现分布式事务的,先从jotm提及