<a href="http://my.oschina.net/pingpangkuangmo/blog/413518">分布式事務系列(開篇)提出疑問和研究過程</a>
<a href="http://my.oschina.net/pingpangkuangmo/blog/415162">分布式事務系列(1.1)spring事務管理器platformtransactionmanager源碼分析</a>
<a href="http://my.oschina.net/pingpangkuangmo/blog/416038">分布式事務系列(1.2)spring事務體系</a>
<a href="http://my.oschina.net/pingpangkuangmo/blog/417479">分布式事務系列(2.1)分布式事務模型與接口定義</a>
<a href="http://my.oschina.net/pingpangkuangmo/blog/419374">分布式事務系列(3.1)jotm的分布式案例</a>
<a href="http://my.oschina.net/pingpangkuangmo/blog/420831">分布式事務系列(3.2)jotm分布式事務源碼分析</a>
<a href="http://my.oschina.net/pingpangkuangmo/blog/423210">分布式事務系列(4.1)atomikos的分布式案例</a>
dtp全稱是distributed transaction process,即分布式事務模型。之前我們接觸的事務都是針對單個資料庫的操作,如果涉及多個資料庫的操作,還想保證原子性,這就需要使用分布式事務了。而x/open dtp就是一種分布式事務處理模型。
x/open是一個組織,維基百科上這樣說明:
x/open是1984年由多個公司聯合建立的一個用于定義和推進資訊技術領域開放标準的公司
上述組織就針對分布式事務提出了一個模型,即dtp模型(distributed transaction process),該模型如下所示:
上面主要涉及了三個對象:
ap(application program):應用程式
tm(transaction manager):事務管理器
負責協調和管理事務,它和之前說的spring的事務管理器platformtransactionmanager可不一樣。
rm(resource manager):資料總管
可以了解為資料庫或者jms。
他們三者的關系:
ap通過tm來操作多個rm,ap也可以通過rm的本地事務接口來操作單個rm
tm和rm可以互相通信,他們之前的通信協定就是xa協定
全稱是the two-phase commit protocol,簡稱2pc
當需要協調多個資料總管進行分布式事務的時候,就需要使用到兩階段送出協定,如下圖所示:
第一個階段:事務管理器通過xa協定,向資料總管發送prepare指令,詢問他們預送出是否成功,每個資料總管給出自己的響應,預送出成功或者失敗
第二個階段:根據第一個階段的資料總管的回複情況,如果全部表示預送出成功,則事務管理器向所有的資料總管發送最終的送出指令。如果有一個資料總管回複預送出失敗,則事務管理器向所有的資料總管發送復原指令,全部進行復原
通過這樣的兩階段送出協定,即可完成了分布式事務的功能。這樣的協定的正是基于了事務管理器和資料總管的雙向通信能力,而這在之前的本地事務中,如jdbc事務中,我們隻能通過connection向資料庫傳遞指令,不能從資料庫擷取事務的一些執行資訊,這種情況是單向的。
然而還是存在一些問題的:
兩階段送出協定是阻塞式協定,是以事務管理器必須等待每一個資料總管發送回複之後,才能進行下一步操作。一旦資料總管挂掉,事務管理器則收不到響應,就會造成事務管理器一直等待。這時候就必須引入逾時機制,一旦超過某個時間還沒有回複,則認為失敗,復原所有操作,這些都是非常耗性能的。
一旦事務管理器挂掉,則資料總管則一直等待事務管理器的指令。這時候可能就需要使用備份的事務管理器來接替原來的事務管理器的工作
更多資料與問題,見如下:
<a href="http://www.infoq.com/cn/minibooks/jtds">infoq上的java事務設計政策</a>
<a href="http://book.51cto.com/art/201309/410608.htm">兩階段送出協定</a>
上述接口規範不是針對某種語言的,java是如何來落實上述規範的呢?這就是jta的内容了。先來預覽下jta的包結構:
主要2個大包的内容:
javax.transaction
javax.transaction.xa
ap:我們的應用程式
tm:即javax.transaction.transactionmanager 事務管理器
rm:即javax.transaction.xa.xaresource 我稱之為與資料總管的一個通信代表,我們通過xaresource接口方法和資料總管進行通信
下面來詳細說明:
tm:即javax.transaction.transactionmanager,總體接口定義如下:
begin():建立一個新的事務并關聯到目前線程
transaction gettransaction():擷取與目前線程關聯的事務
commit():送出與目前線程關聯的事務
rollback():復原與目前線程關聯的事務
等等
定義了一些常用的事務操作,這裡操作的事務的定義為javax.transaction.transaction,接口如下所示:
commit():送出事務
rollback():復原事務
enlistresource(xaresource xares):把給定的xaresource(資料總管的一個通信代表)加入目前事務中來,一個分布式事務會涉及與多個資料總管互動,該操作就是把某個資料總管的通信代表納入目前事務中來
delistresource(xaresource xares, int flag):把給定的xaresource(資料總管的一個通信代表)從目前事務中去除
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的其他方法
start(xid xid, int flags)和end(xid xid, int flags)用于告知資料總管的事務的邊界,即在這兩個方法之間的sql等操作才會納入xid對應的分布式事務中
prepare(xid xid):則就是上述圖檔中的第一個階段,針對xid對應的分布式事務,向資料總管發送預送出指令
rollback(xid xid)、commit(xid xid, boolean onephase) 如果所有資料總管都回複ok,則向所有資料總管發送commit送出指令,否則發送rollback復原指令
下面看一個簡單模拟兩階段送出的例子,加深對上面的方法的了解:
過程說明:
首先使用start、end來告知資料總管分布式事務的邊界,上述stmt1.executeupdate("insert into test_table1 values (99)");沒有在start、end範圍之内,則不會劃入分布式事務的管轄中,而是作為了一般的本地事務。
然後周遊每個資料總管的通信代表,使他們詢問資料總管預送出的情況
如果全部ok則全部送出,否則全部復原
usertransaction接口是給開發人員使用的事務接口,屏蔽了底層的實作細節,通過該接口就可以操作一個分布式事務。該接口的實作通常是委托給tm即事務管理器來完成。接口内容如下:
可以看到,usertransaction的這些方法在tm即事務管理器中都有對應的方法。
涉及到哪些角色呢?他們的職責與任務分别什麼呢?
開發人員:隻需通過使用usertransaction接口來進行操作分布式事務
transactionmanager的實作提供者:實作usertransaction、transactionmanager、transaction接口,通過與xaresource接口互動來實作分布式事務,transactionmanager的實作提供者如jotm、atomikos,他們的上述接口分别如下
1.1 jotm的usertransaction實作是org.objectweb.jotm.current
1.2 jotm的transactionmanager實作仍然是org.objectweb.jotm.current
1.3 jotm的transaction實作是org.objectweb.jotm.transactionimpl
2.1 atomikos的usertransaction實作是com.atomikos.icatch.jta.usertransactionimp
2.2 atomikos的transactionmanager實作是com.atomikos.icatch.jta.usertransactionmanager
2.3 atomikos的transaction實作是com.atomikos.icatch.jta.transactionimp
xaresource接口的實作者:需要由資料總管者來實作,若資料總管是資料庫,則資料庫需要提供xaresource接口的實作。如對于mysql來說,對應的實作為 com.mysql.jdbc.jdbc2.optional.mysqlxaconnection。這種形式下的資料庫驅動就是支援分布式事務的資料庫驅動
jts是什麼呢?它和jta是什麼關系呢?
jts也定義了一套規範,它約定了各個程式角色之間如何傳遞事務上下文,它源自corba 的ots規範,基于iiop(一種軟體互動協定)。不要認為jts是jta的實作,jta其實就定義了一個空架子,告訴jta的實作者應該怎樣做怎樣做,但是具體到做的時候jts就來插一手了。因為jta約定的這些角色要進行事務上下文的互動啊,jts約定了應該怎樣去進行互動
1 是不是資料庫驅動必須要支援xa協定,即支援分布式事務?
不是,可以使用第三方架構如jotm、atomikos來模拟xa協定
2 使用分布式事務,是不是一定要應用伺服器的支援?
不是。
jboss是支援的,是以我們可以直接使用jboss自己實作的usertransaction來實作分布式事務(使用jndi方式,這時候要求資料庫驅動支援xa協定),可以不需要像jotm、atomikos等第三方架構
tomcat就是不支援的,但是我們可以使用第三方架構來實作,如jotm、atomikos
這一篇這要了解了分布式事務的一些概念與jta的接口定義,下一步就開始深入源碼分析jotm、atomikos是如何來實作分布式事務的,先從jotm說起
jotm實作分布式事務的例子
jotm的實作原理