zoukankan      html  css  js  c++  java
  • JPA和分布式事务简介

    1. Transaction 分两种,Local Transaction 和 Global Transaction。 
    涉及到一个Connection的Commit,称为Local Transaction。 
    涉及到多个Connection的Commit,称为Global Transaction。 
    楼主提到的是,Global Transaction. 

    2. Global Transaction 需要XA接口(包括在JTA里面)的支持。 

    import javax.sql.XAConnection; 
    import javax.transaction.xa.Xid; 
    import javax.transaction.xa.XAResource; 
    import javax.transaction.xa.XAException; 
    import javax.transaction.Transaction; 
    import javax.transaction.TransactionManager; 

    其中的 
    javax.sql.XAConnection; 
    javax.transaction.xa.Xid; 
    javax.transaction.xa.XAResource; 

    这些XA接口的实现,需要数据库的JDBC提供。 
    数据库本身要支持XA。数据库的JDBC也要提供XA的实现。 

    Oracle, Sybase, DB2, SQL Server等大型数据库才支持XA, 支持Global Transaction。 
    My SQL 连Local Transaction都支持不好,更别说Global Transation了。 

    3. XA需要两阶段提交 -- prepare 和 commit. 
    假设有两个Connection, con1, con2, 大体的过程如下, 

    con1 = XAResouce1.getConnection...
    con2 = XAResouce2.getConnection...
    
    con1 do some thing.
    con2 do some thing.
    after they finish.
    
    pre1 = XAResouce1.prepare();
    pre2 = XAResouce2.prepare();
    
    if( both pre1 and pre2 are OK){
    XAResouce1 and 2 commit
    }else {
    XAResouce1 and 2 rollback
    }

    前面有人讲了,在XAResouce1 and 2 commit的时候, 
    可能XAResouce1 commit() 成功了,XAResouce2 commit()失败了。 
    这时候,会抛出一个 “启发式异常”。程序可以处理这个异常。比如,XAResouce.recover()之类。 
    但一般情况下,还真没别的办法,需要数据管理员根据数据操作日志 undo所有的操作,或者恢复数据备份。 
    有的数据库在进行数据操作的时候,会生成一个“反操作”日志。比如,insert 对 delete, 等。 

    4. TransactionManager的实现能够处理多个XAResouce(一个XAResouce list)的情况。 
    比如Tyrex。或JBoss等EJB Server的Transaction实现代码

    注释:XA:XA协议由Tuxedo首先提出的,并交给X/Open组织,作为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通信的标准接口。XA协议包括两套函数,以xa_开头的及以ax_开头的。

    以下的函数使事务管理器可以对资源管理器进行的操作:

      1)xa_open,xa_close:建立和关闭与资源管理器的连接。

      2)xa_start,xa_end:开始和结束一个本地事务。

      3)xa_prepare,xa_commit,xa_rollback:预提交、提交和回滚一个本地事务。

      4)xa_recover:回滚一个已进行预提交的事务。

      5)ax_开头的函数使资源管理器可以动态地在事务管理器中进行注册,并可以对XID(TRANSACTION IDS)进行操作。

      6)ax_reg,ax_unreg;允许一个资源管理器在一个TMS(TRANSACTION MANAGER SERVER)中动态注册或撤消注册。

    JTA和JTS

    JTA

    JTA定义了一套接口,其中约定了几种主要的角色:TransactionManager、UserTransaction、Transaction、XAResource,并定义了这些 角色之间需要遵守的规范,如Transaction的委托给TransactionManager等。

    JTS

    JTS也是一组规范,上面提到JTA中需要角色之间的交互,那应该如何交互?JTS就是约定了交互细节的规范。

    总体上来说JTA更多的是从框架的角度来约定程序角色的接口,而JTS则是从具体实现的角度来约定程序角色之间的接口,两者各司其职。

    因为JTA相对来说,更高层一些,我们主要关注JTA。

    XA

    XA协议,规定事务管理器和资源管理器接口,采用二阶段提交协议。

    JTA事务有效的屏蔽了底层事务资源,但是与本地事务相比,XA协议的系统开销大。

    总结

    关键接口

    先介绍一下JTA的规范接口中,主要围绕以下几个接口:

    • UserTransaction:编程人员接口
    • TransactionManager:留给厂商实现的与事务管理有关的接口
    • Transaction:留给厂商实现的事务
    • XAResource:留给厂商实现的与持久化资源有关的接口

    接口类中的接口定义可参见源码,几个接口类关系如下:

    下载了JBoss的JTA实现源码,但是发现深入这个源码有难度,且需要的时间也会较长,故留着以后学习。JBoss的JTA实现是Narayana,SVN地址为https://github.com/jbosstm/narayana,如果有兴趣可以研究一下。

    二阶段提交协议

    所以在一阶段协议的基础上,有了二阶段协议,二阶段协议的好处是添加了一个管理者角色,如下:

    很明显,二阶段协议通过将两层变为三层,增加了中间的管理者角色,从而协调多个数据源之间的关系,二阶段提交协议分为两个阶段。

    应用程序调用了事务管理器的提交方法,此后第一阶段分为两个步骤:

    • 事务管理器通知参与该事务的各个资源管理器,通知他们开始准备事务。
    • 资源管理器接收到消息后开始准备阶段,写好事务日志并执行事务,但不提交,然后将是否就绪的消息返回给事务管理器(此时已经将事务的大部分事情做完,以后的内容耗时极小)。

    第二阶段也分为两个步骤:    

    • 事务管理器在接受各个消息后,开始分析,如果有任意其一失败,则发送回滚命令,否则发送提交命令。
    • 各个资源管理器接收到命令后,执行(耗时很少),并将提交消息返回给事务管理器。
        事务管理器接受消息后,事务结束,应用程序继续执行。
        为什么要分两步执行?一是因为分两步,就有了事务管理器统一管理的机会;二尽可能晚地提交事务,让事务在提交前尽可能地完成所有能完成的工作,这样,最后的提交阶段将是耗时极短,耗时极短意味着操作失败的可能性也就降低。
        同时,二阶段提交协议为了保证事务的一致性,不管是事务管理器还是各个资源管理器,每执行一步操作,都会记录日志,为出现故障后的恢复准备依据。
        二阶段提交协议的存在的弊端是阻塞,因为事务管理器要收集各个资源管理器的响应消息,如果其中一个或多个一直不返回消息,则事务管理器一直等待,应用程序也被阻塞,甚至可能永久阻塞。
  • 相关阅读:
    java使用io流读取windows文件乱码问题
    java的io字符流关闭和刷新.flush();
    java使用io流实现图片复制
    java8新特性-函数式接口详细讲解及案例
    java8的lambda过滤list遍历集合,排序
    java复制对象,复制对象属性,只可复制两个对象想同的属性名。也可自定义只复制需要的属性。
    详讲KMP算法
    java栈和队列
    请求中文乱码解决
    idea创建servlet步骤
  • 原文地址:https://www.cnblogs.com/onlywujun/p/4784233.html
Copyright © 2011-2022 走看看