現目前處理分佈式事務的方案有不少,好比java
而實現了對應的協議的有mysql
對於 XA 協議來講,它使用的是 2PC 協議的方式,是阻塞式的,而且它還依賴於數據庫自身提供的 XA 接口的可靠性,對於大部分商業數據庫來講作的都還蠻不錯,在 Mysql 中只有 InnoDB 引擎支持 XA 分佈式事務。git
基於 XA 的分佈式事務方案更適用於單機應用中跨庫事務,它也能夠作到遠程調用事務支持github
XA 協議由 Tuxedo 首先提出的,並交給X/Open組織,這個組織隨即定義了一套分佈式事務的標準即 X/Open DTP(X/Open Distributed Transaction Processing Reference Model) 即一些列的接口各個廠商須要遵循這個標準來實現sql
在 DTP 模型中定義了五個組成元素數據庫
其中在 DTP 中又定義瞭如下幾個概念編程
DTP 模型主要是經過 2PC 來控制事務管理器和資源管理之間的交互的api
優勢:能夠作到對業務無侵入,可是對事務管理器和資源管理器要求比較高服務器
缺點:網絡
能夠看出 2PC 協議存在阻塞低效和數據不一致的問題,因此在大型應用須要較高的吞吐量的應用是不多使用這種方案的
JTA(Java Transaction API)即 Java 事務 API 和 JTS(Java Transaction Service)即 Java 事務服務,他們爲 JAVA 平臺提供了分佈式事務服務,能夠把 JTA 理解爲是 XA 協議規範的 Java 版本。它也採用的是 DTP 模型
咱們知道 JTA 它只是一個規範,定義瞭如何去於實現了 XA 協議的資源管理器交互的接口,可是並無對應的實現,官方推薦 Atomikos 來實現 XA 分佈式事務,感謝的能夠直接取研究 Atomikos 源碼。
能夠經過對 XA 協議的實際應用來加深咱們的理解,代碼以下
public static void test() {
try {
// 開啓全局事務
transactionManager.begin();
// 向服務器 A 數據庫寫入數據
saveDB1();
// 向服務器 B 數據庫寫入數據
saveDB2();
// 詢問 RM 分支事務是否準備就緒
boolean prepareSuccess = transactionManager.prepare();
// 目前沒有涉及到遠程事務的支持,在本地都是同步的方式調用因此此處沒有作作阻塞等待而是返回馬上知道是否成功
// 若是涉及到遠程事務的支持,那麼此處應該就有一個阻塞喚醒機制
if (prepareSuccess) {
// 開始提交分支事務
transactionManager.commit();
} else {
// 回滾
transactionManager.rollback();
}
} catch (Exception e) {
e.printStackTrace();
// 若是出錯了就進行回滾各分支事務
try {
transactionManager.rollback();
} catch (Exception e1) {
e1.printStackTrace();
}
} finally {
// 資源回收
GlobalInfo.remove();
}
}
private static void saveDB1() throws XAException, SQLException {
// 由於存在多個數據源,因此須要指定是使用哪個數據源
XAResourceManager xaResourceManager = RMUtil.getResourceManager(dbPool1);
// 分支事務開啓
xaResourceManager.begin();
xaResourceManager.execute("insert into test1(name, age) values('pt', 21)");
// 事務執行完畢處於準備階段等待 TM 下達 commit 指令
xaResourceManager.prepare();
}
private static void saveDB2() throws XAException, SQLException {
XAResourceManager xaResourceManager = RMUtil.getResourceManager(dbPool2);
// 分支事務開啓
xaResourceManager.begin();
xaResourceManager.execute("insert into test2(name, age) values('tom', 22)");
// 事務執行完畢處於準備階段等待 TM 下達 commit 指令
xaResourceManager.prepare();
// 測試回滾
// throw new RuntimeException("xx");
}
複製代碼
代碼放在了 github 上面感興趣的能夠了解一下
參考: