我覺得事務的管理不應該屬於Dubbo框架,
Dubbo只需實現可被事務管理即可,
像JDBC和JMS都是可被事務管理的分散式資源,
Dubbo只要實現相同的可被事務管理的行為,比如可以回滾,
其它事務的排程,都應該由專門的事務管理器實現。
在Java中,分散式事務主要的規範是JTA/XA,
其中:JTA是Java的事務管理器規範,
XA是工業標準的X/Open CAE規範,可被兩階段提交及回滾的事務資源定義,
比如某資料庫實現了XA規範,則不管是JTA,還是MSDTC,都可以基於同樣的行為對該資料庫進行事務處理。
在JTA/XA中,主要有兩個擴充套件點:
(1) TransactionManager
JTA事務管理器介面,實現該介面,即可完成對所有XA資源的事務排程,比如BEA的Tuxedo,JBossJTA等。
(2) XAResource
XA資源介面,實現該介面,即可被任意TransactionManager排程,比如:JDBC的XAConnection,JMS的XAMQ等。
而Dubbo的遠端服務,也應該是一個XAResource,比如:XAInvoker和XAExporter,
Dubbo只需在第一次提交時,將請求發到服務提供方進行快取和寫盤,
在第二次提交時,再基於快取呼叫服務的Impl實現,
當然一些健狀性分支流程要考慮清楚。
JTA/XA的基本原理如下:
1. 使用者啟動一個事務:
2. 事務管理器在當前執行緒中初始化一個事務例項:
3. 使用者呼叫JDBC或JMS或Dubbo請求,請求內部初始化一個XAResource例項:
4. JDBC或JMS或Dubbo內部從當前執行緒獲取事務:
5. 將當前XAResource註冊到事務中:
6. 使用者提交一個事務:
7. 事務for迴圈呼叫所有註冊的XAResource的兩階段提交:
8. 當然,還有一些異常流程,比如rollback和forget等。
舉例:
Dubbo只需實現可被事務管理即可,
像JDBC和JMS都是可被事務管理的分散式資源,
Dubbo只要實現相同的可被事務管理的行為,比如可以回滾,
其它事務的排程,都應該由專門的事務管理器實現。
在Java中,分散式事務主要的規範是JTA/XA,
其中:JTA是Java的事務管理器規範,
XA是工業標準的X/Open CAE規範,可被兩階段提交及回滾的事務資源定義,
比如某資料庫實現了XA規範,則不管是JTA,還是MSDTC,都可以基於同樣的行為對該資料庫進行事務處理。
在JTA/XA中,主要有兩個擴充套件點:
(1) TransactionManager
JTA事務管理器介面,實現該介面,即可完成對所有XA資源的事務排程,比如BEA的Tuxedo,JBossJTA等。
(2) XAResource
XA資源介面,實現該介面,即可被任意TransactionManager排程,比如:JDBC的XAConnection,JMS的XAMQ等。
而Dubbo的遠端服務,也應該是一個XAResource,比如:XAInvoker和XAExporter,
Dubbo只需在第一次提交時,將請求發到服務提供方進行快取和寫盤,
在第二次提交時,再基於快取呼叫服務的Impl實現,
當然一些健狀性分支流程要考慮清楚。
JTA/XA的基本原理如下:
1. 使用者啟動一個事務:
- transactionManager.begin();
2. 事務管理器在當前執行緒中初始化一個事務例項:
- threadLocal.set(new TransactionImpl());
3. 使用者呼叫JDBC或JMS或Dubbo請求,請求內部初始化一個XAResource例項:
- XAResource xaResource = new XAResourceImpl(); // 比如:XAConnection
4. JDBC或JMS或Dubbo內部從當前執行緒獲取事務:
- Transaction transaction = transactionManager.getTransaction(); // 其內部為:threadLocal.get();
5. 將當前XAResource註冊到事務中:
- transaction.enlistResource(xaResource);
6. 使用者提交一個事務:
- transactionManager.commit(); // 其內部為:getTransaction().commit();
7. 事務for迴圈呼叫所有註冊的XAResource的兩階段提交:
- Xid xid = new XidImpl();
- for (XAResource xaResource: xaResources) {
- xaResource.prepare(xid);
- xaResource.commit(xid, true);
- xaResource.commit(xid, false);
- }
8. 當然,還有一些異常流程,比如rollback和forget等。
舉例:
- TransactionManager transactionManager = ...; // 從JNDI進行lookup等方式獲取
- transactionManager.begin(); // 啟動事務
- try {
- jdbcConn.executeUpdate(sql); // 執行SQL語句,DB寫入binlog,但不更新表
- jmsMQ.send(message); // 傳送訊息,MQ記錄訊息,但不進入佇列
- dubboService.invoke(parameters); // 呼叫遠端服務,Provider快取請求資訊,但不執行
- transactionManager.commit(); // 提交事務,資料庫,訊息佇列,遠端服務同時提交
- } catch(Throwable t) {
- transactionManager.rollback(); // 回滾事務,資料庫,訊息佇列,遠端服務同時回滾
- }