#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提及