剛性事務
1.DTP模型
X/Open組織介紹
X/OPEN是一個組織(現在的open group)X/Open國際聯盟有限公司是一個歐洲基金會,它的建立是為了向UNIX環境提供標準。它主要的目標是促進對UNIX語言、接口、網絡和應用的開放式系統協議的制定。它還促進在不同的UNIX環境之間的應用程序的互操作性,以及支持對電氣電子工程師協會(IEEE)對UNIX的可移植操作系統接口(POSIX)規范
主要成員
DTP模型介紹
X/Open DTP(Distributed Transaction Process)是一個分布式事務模型。這個模型主要使用了兩段提交(2PC - Two-Phase-Commit)來保證分布式事務的完整性
這套標準主要定義了實現分布式事務的規范和API,具體的實現則交給相應的?商來實現
X/Open提供的參考文檔
- DTP 參考模型:http://pubs.opengroup.org/onlinepubs/9294999599/toc.pdf
- DTP XA規范:http://pubs.opengroup.org/onlinepubs/009680699/toc.pdf
相關概念
- 事務:?個事務就是?個完整的?作單元,具備ACID特性
- 全局事務:由事務管理器管理的事務,能夠?次性操作多個資源管理器
- 分?事務:由事務管理器管理的全局事務中,每個資源管理器中獨?執?的事務
- 控制線程:執?全局事務的線程,這個線程?來關聯應?程序、事務管理器和資源管理器 三者之間的關系,也就是表示全局事務和分?事務的關系,通常稱為事務上下?環境
核心組件
- AP:應用程序(Application Program)用于定義事務邊界(即定義事務的開始和結束),并且在事務邊界內對資源進行操作,可以理解為參與DTP分布式事務模型的應?程序
- RM:資源管理器(Resource Manager)可以理解為數據庫管理系統或消息服務管理器。應?程序可以通過資源管理器對相應的資源進?有效的控制。相應的資源需要實現XA定義的接?
- TM:事務管理器(Transaction Manager)負責分配事務唯一標識,監控事務的執行進度,并負責全局事務的提交、回滾等,為應?程序提供編程接?
- CRM(不重要):通信資源管理器(Communication Resource Manager)控制一個TM域(TM domain)內或者跨TM域的分布式應用之間的通信
- CP(不重要):通信協議(Communication Protocol)提供CRM提供的分布式應用節點之間的底層通信服務
注意
- DTP模型定義了XA接?,TM和RM能夠通過XA接?進?雙向通信。TM控制著全局事務,管理事務的?命周期并協調資源。 RM控制和管理實際的資源
- 一個DTP模型實例,至少有3個組成部分:AP、RM、TM,也叫做DTP本地模型實例
執行流程
2.兩階段提交協議(2PC)
為什么會誕生2PC和3PC
在分布式系統中,會有多個機器節點,每一個機器節點雖然能夠明確地知道自己在進行事務操作過程中的結果是成功或失敗,但無法直接獲取到其他分布式節點的操作結果,因此,當一個事務操作需要跨越多個分布式節點的時候,為了保證事務處理的ACID特性,就需要引入一個“協調者”的組件來統一調度所有分布式節點的執行邏輯,這些被調度的節點則稱為“參與者”,協調者負責調度參與者的行為,并最終決定這些參與者是否要把事務真正進行提交。基于這個思想,就衍生了二階段提交和三階段提交兩種協議
介紹
2PC,是Two Phase Commit縮寫,即兩階段提交。準備階段(Prepare phase)、提交階段(commitphase)。是計算機網絡,尤其是數據庫領域中,為了使基于分布式系統架構下的所有節點在進行事務處理過程中能夠保持原子性和一致性而設計的一種算法,通常,2PC也被認為是一種一致性協議,用來保證分布式系統數據的一致性,目前,絕大部分的關系型數據庫都是采用二階段提交協議來完成分布式事務處理的,利用該協議能夠非常方便地完成所有分布式事務參與者的協調,統一決定事務的提交和回滾,從而能夠有效地保證分布式數據的一致性
角色
- 協調者(Coordinater):事務管理器(TM)
- 參與者(participants):資源管理器(RM)
整體執行流程
Prepare階段
- 事務詢問:協調者向所有的參與者發送事務內容,詢問是否可以執行事務提交請求,并開始等待各參與者的響應
- 執行事務但不提交:各參與者節點執行事務操作,并將Undo和Redo信息記入事務日志中
- 參與者向協調者反饋事務詢問的響應:如果參與者成功執行了事務操作,那么就反饋給協調者Yes的響應,表示事務可以執行。如果參與者沒有成功執行事務,就返回No給協調者,表示事務不可執行。還有可能參與者根本沒接收到事務詢問所以沒有響應
Commit階段之執行事務
- 發送提交請求:協調者向所有參與者發出commit請求
- 事務提交:參與者收到commit請求后,會正式執行事務提交操作,并在完成提交之后釋放整個事務執行期間占用的事務資源
- 反饋事務提交結果:參與者在完成事務提交之后,向協調者發送Ack信息
- 完成事務:協調者接收到所有參與者反饋的Ack信息后,完成事務
Commit階段之回滾事務
- 發送回滾請求:協調者向所有參與者發出Rollback請求
- 事務回滾:參與者接收到Rollback請求后,會利用其在階段一中記錄的Undo信息來執行事務回滾操作,并在完成回滾之后釋放在整個事務執行期間占用的資源
- 反饋事務回滾結果:參與者在完成事務回滾之后,向協調者發送Ack信息
- 中斷事務:協調者接收到所有參與者反饋的Ack信息后,完成事務中斷
問題
- 同步阻塞問題:在二階段提交的執行過程中,所有參與該事務操作的邏輯都處于阻塞狀態,也就是說,各個參與者在等待其他參與者響應的過程中,無法進行其他操作。這種同步阻塞極大的限制了分布式系統的性能
- 單點故障問題:協調者在整個二階段提交過程中很重要,如果協調者在提交階段出現問題,那么整個流程將無法運轉,更重要的是,其他參與者將會處于一直鎖定事務資源的狀態中,而無法繼續完成事務操作
- 數據不?致問題:假設當協調者向所有的參與者發送commit請求之后,發生了局部網絡異常或者是協調者在尚未發送完所有commit請求之前自身發生了崩潰,導致最終只有部分參與者收到了commit請求。這將導致嚴重的數據不一致問題
- 過于保守:如果在事務詢問中,參與者出現故障而導致協調者始終無法獲取到所有參與者的響應信息的話,這時協調者只能依靠其自身的超時機制來判斷是否需要中斷事務,顯示,這種策略過于保守。換句話說,二階段提交協議沒有設計較為完善的容錯機制,任意一個節點失敗都會導致整個事務的失敗
使用場景
- 單個服務操作多個數據庫
- 并發不高
3.三階段提交協議(3PC)
介紹
3PC,全稱“three phase commit”,是2PC的改進版,將2PC的“提交事務請求”過程一分為二,共形成了由CanCommit,PreCommit和doCommit三個階段組成的事務處理協議
相比于二階段提交改進的地方
- 在協調者與參與者都引入了超時機制(在2PC中,只有協調者擁有超時機制,既如果在一定時間內沒有收到參與者的消息則默認失效)
- 當進入第三階段,由于網絡超時等原因,雖然參與者沒有收到commit或abort響應,但是它有理由相信,成功提交的幾率很大
整體流程
CanCommit階段
- 事務詢問:協調者向所有的參與者發送一個包含事務內容的canCommit請求,詢問是否可以執行事務提交操作,并開始等待各參與者的響應
- 各參與者向協調者反饋事務詢問的響應:參與者在接收到來自協調者的包含了事務內容的canCommit請求后,正常情況下,如果自身認為可以順利執行事務,則反饋Yes響應,并進入預備狀態,否則反饋No響應
PreCommit階段之執行事務預提交
- 發送預提交請求:協調者向所有參與者節點發出preCommit請求,并進入prepared階段
- 事務預提交:參與者接受到preCommit請求后,會執行事務操作,并將Undo和Redo信息記錄到事務日志中
- 各參與者向協調者反饋事務執行的結果:若參與者成功執行了事務操作,那么反饋Ack,同時等待最終的指令:提交或終止
PreCommit階段之執行中斷事務
- 發送中斷請求:協調者向所有參與者發出abort請求
- 中斷事務:無論是收到來自協調者的abort請求或者等待協調者請求過程中超時,參與者都會中斷事務
DoCommit階段之執行事務提交
- 發送提交請求:進入這一階段,假設協調者處于正常工作狀態,并且它接收到了來自所有參與者的Ack響應,那么它將從預提交狀態轉換為提交狀態,并向所有的參與者發送doCommit請求
- 事務提交:參與者接收到doCommit請求后,會正式執行事務提交操作,并在完成提交之后釋放整個事務執行過程中占用的事務資源
- 反饋事務提交結果:參與者在完成事務提交后,向協調者發送Ack響應
- 完成事務:協調者接收到所有參與者反饋的Ack消息后,完成事務
DoCommit階段之中斷事務
- 發送中斷請求:協調者向所有的參與者節點發送abort請求
- 事務回滾:參與者接收到abort請求后,會根據記錄的Undo信息來執行事務回滾,并在完成回滾之后釋放整個事務執行期間占用的資源
- 反饋事務回滾結果:參與者在完成事務回滾后,向協調者發送Ack信息
- 中斷事務:協調者接收到所有參與者反饋的Ack信息后,中斷事務
進入階段三可能會出現兩種故障
- 協調者出現問題
- 協調者和參與者之間的網絡故障
如果出現了任意一種情況,最終都會導致參與者無法收到doCommit請求或者abort請求,針對這種情況,參與者都會在等待超時之后,繼續進行事務提交
優缺點
優點
相比較于2PC,最大的優點就是降低了參與者的阻塞范圍(第一個階段是不阻塞的),其次能夠在單點故障后繼續達成一致(2PC在提交階段會出現此問題,而3PC會根據協調者的狀態進行回滾或提交)
缺點
階段三發送abort請求的時候,出現了網絡分區(有的節點收到了abort請求有的沒有),此時協調者所在的節點和參與者所在的節點無法進行正常的網絡通信,那么參與者等待超時后,會進行事務的提交,這必然會出現分布式數據不一致的問題
4.XA協議
作用
XA規范的最主要的作用是,就是定義了RM-TM的交互接口,下圖更加清晰了演示了XA規范在DTP模型中發揮作用的位置,從下圖中可以看出來,XA僅僅出現在RM和TM的連線上
官方說法
- XA 規范 是 X/Open 組織定義的分布式事務處理(DTP,Distributed Transaction Processing)標準
- XA 規范 描述了全局的事務管理器與局部的資源管理器之間的接口。 XA規范 的目的是允許的多個資源(如數據庫,應用服務器,消息隊列等)在同一事務中訪問,這樣可以使 ACID 屬性跨越應用程序而保持有效
- XA 規范 最終完成兩階段提交(2PC,Two-Phase Commit)協議來保證所有資源同時提交或回滾任何特定的事務
- XA 規范 在上世紀 90 年代初就被提出。目前,幾乎所有主流的數據庫都對 XA 規范 提供了支持
常見的誤解
有些人可能會誤認為兩階段提交協議是在XA規范中提出來的。事實上: 兩階段協議是在OSI TP標準中提出的;在DTP參考模型中,指定了全局事務的提交要使用two-phase commit協議;而XA規范只是定義了兩階段提交協議中需要使用到的接口,也就是上述提到的RM-TM交互的接口,因為兩階段提交過程中的參與方,只有TM和RMs
介紹
XA規范(XA Specification) 是X/OPEN 提出的分布式事務處理規范。XA則規范了TM與RM之間的通信接口,在TM與多個RM之間形成一個雙向通信橋梁,從而在多個數據庫資源下保證ACID四個特性。目前知名的數據庫,如Oracle, DB2,mysql等,都是實現了XA接口的,都可以作為RM
XA是數據庫的分布式事務,強一致性,在整個過程中,數據一直鎖住狀態,即從prepare到commit、rollback的整個過程中,TM一直把持這數據庫的鎖,如果有其他人要修改數據庫的該條數據,就必須等待鎖的釋放,存在長事務風險
準確講XA是一個規范、協議,它只是定義了一系列的接口,只是目前大多數實現XA的都是數據庫或者MQ,所以提起XA往往多指基于資源層的底層分布式事務解決方案。其實現在也有些數據分片框架或者中間件也支持XA協議,畢竟它的兼容性、普遍性更好
規定中RM提供的接口
- xa_open,xa_close:建立和關閉與資源管理器的連接
- xa_start,xa_end:開始和結束一個本地事務
- xa_prepare,xa_commit,xa_rollback:預提交、提交和回滾一個本地事務
- xa_recover:回滾一個已進行預提交的事務
- ax_開頭的函數使資源管理器可以動態地在事務管理器中進行注冊,并可以對XID(TRANSACTION IDS)進行操作
- ax_reg,ax_unreg:允許一個資源管理器在一個TMS(TRANSACTION MANAGER SERVER)中動態注冊或撤消注冊
XA各個階段的處理流程
支持XA協議的常見分布式事務框架
- Atomikos
- Seata
5.JTA規范
規范下載地址
https://download.oracle.com/otn-pub/jcp/jta-1.1-spec-oth-JSpec/jta-1_1-spec.pdf?AuthParam=1678249590_c72c2e509ad94b22138dce2f61f66b12
介紹
它是JavaEE的13個規范之一
Java事務API/Java平臺事務規范(JTA:Java Transaction API)和它的同胞Java事務服務(JTS:Java Transaction Service),為J2EE平臺提供了分布式事務服務(distributed transaction)的能力。 某種程度上,可以認為JTA規范是XA規范的Java版,其把XA規范中規定的DTP模型交互接口抽象成Java接口中的方法,并規定每個方法要實現什么樣的功能
JTA是基于XA架構上建模的,在JTA 中,事務管理器抽象為javax.transaction.TransactionManager接口,并通過底層事務服務(即JTS)實現。像很多其他的java規范一樣,JTA僅僅定義了接口
JTA的常見實現
JTA規范規定,事務管理器的功能應該由application server提供,如EJB Server。一些常見的其他web容器,如:jboss、weblogic、websphere等,都可以作為application server,這些web容器都實現了JTA規范。特別需要注意的是,并不是所有的web容器都實現了JTA規范,如tomcat并沒有實現JTA規范,因此并不能提供事務管理器的功能
- J2EE容器所提供的JTA實現(JBoss)
- 獨立的JTA實現:如JOTM,Atomikos,這些實現可以應用在那些不使用J2EE應用服務器的環境里用以提供分布事事務保證。如Tomcat,Jetty以及普通的java應用
接口定義
依賴
JTA是java擴展包,在應用中需要額外引入相應的jar包依賴
<dependency><groupId>javax.transaction</groupId><artifactId>jta</artifactId><version>1.1</version>
</dependency>
重要類含義
JTA規范中定義的這些接口,并不需要應用程序的開發人員去實現。而是由各個廠商去實現,根據在DTP模型中扮演的不同角色,需要實現不同的接口
- javax.transaction.Status:事務狀態,這個接口主要是定義一些表示事務狀態的常量,此接口無需實現
- javax.transaction.Synchronization:同步
- javax.transaction.Transaction:事務
- javax.transaction.TransactionManager:事務管理器
- javax.transaction.UserTransaction:用于聲明一個分布式事務
- javax.transaction.TransactionSynchronizationRegistry:事務同步注冊
- javax.transaction.xa.XAResource:定義RM提供給TM操作的接口
- javax.transaction.xa.Xid:事務id
TM供應商
實現UserTransaction、TransactionManager、Transaction、TransactionSynchronizationRegistry、Synchronization、Xid接口,通過與XAResource接口交互來實現分布式事務。此外,TM廠商如果要支持跨應用的分布式事務,那么還要實現JTS規范定義的接口
常見的TM提供者包括我們前面提到的application server,包括:jboss、ejb server、weblogic等,以及一些以第三方類庫形式提供事務管理器功能的jotm、Atomikos
RM供應商
XAResource接口需要由資源管理器者來實現,XAResource接口中定義了一些方法,這些方法將會被TM進行調用,如:
- start方法:開啟事務分支
- end方法:結束事務分支
- prepare方法:準備提交
- commit方法:提交
- rollback方法:回滾
- recover方法:列出所有處于PREPARED狀態的事務分支
- 一些RM提供者,可能也會提供自己的Xid接口的實現
此外,不同的資源管理器有一些各自的特定接口要實現:
- 如JDBC2.0規范定義支持分布式事務的jdbc driver需要實現:javax.sql.XAConnection、javax.sql.XADataSource接口
- JMS1.0規范規定支持分布式事務的JMS廠商,需要實現javax.jms.XAConnection、javax.jms.XASession接口
注意
作為DTP模型中Application開發者的我們,并不需要去實現任何JTA規范中定義的接口,只需要使用TM提供的UserTransaction實現,來聲明、提交、回滾一個分布式事務即可
使用案例
需要注意的是,在分布式事務中,當我們需要提交或者回滾一個事務時,不應該再使用Connection接口提供的commit和rollback方法。而是應該使用UserTransaction接口的commit接口和rollback接口替代。
另外,在本案例中,我們并沒有說明UserTransaction實例是如何構建的,這是由事務管理器(TM)實現者提供的,而目前我們還沒有接觸過任何事務管理器
UserTransaction userTransaction=...try{//開啟分布式事務userTransaction.begin(); //執行事務分支1conn1 = db1.getConnection();ps1= conn1.prepareStatement("INSERT into user(name,age) VALUES ('tianshouzhi',23)");ps1.executeUpdate();//執行事務分支2conn2 = db2.getConnection();ps2 = conn2.prepareStatement("INSERT into user(name,age) VALUES ('tianshouzhi',23)");ps2.executeUpdate();//提交,兩階段提交發生在這個方法內部userTransaction.commit();}catch (Exception e){try {userTransaction.rollback();//回滾} catch (SystemException ignore) {}}
6.JTS規范
事務是編程中必不可少的一項內容,基于此,為了規范事務開發,Java增加了關于事務的規范,即JTA和JTS
JTA定義了一套接口,其中約定了幾種主要的角色:TransactionManager、UserTransaction、Transaction、XAResource,并定義了這些角色之間需要遵守的規范,如Transaction的委托給TransactionManager等
JTS也是一組規范,上面提到JTA中需要角色之間的交互,那應該如何交互?JTS就是約定了交互細節的規范
總體上來說JTA更多的是從框架的角度來約定程序角色的接口,而JTS則是從具體實現的角度來約定程序角色之間的接口,兩者各司其職
7.Atomikos分布式事務
Atomikos公司旗下有兩款著名的分布事務產品:
- TransactionEssentials:開源的免費產品
- ExtremeTransactions:商業版,需要收費
這兩個產品的關系如下圖所示:
XA的主要限制
- 必須要拿到所有數據源,而且數據源還要支持XA協議。目前MySQL中只有InnoDB存儲引擎支持XA協議
- 性能比較差,要把所有涉及到的數據都要鎖定,是強一致性的,會產生長事務