支付寶分佈式事務服務DTS二

原文連接:https://blog.csdn.net/qq_27384769/article/details/79305133spring

典型場景和實現原理
首先來看一個典型的分佈式事務場景sql

 

 

 

在這個例子中,app1 做爲分佈式事務的發起方調用了參與者 app2 的 insert 操做和 app3 的 update 操做,以後調用本身的本地 insert 操做,在這個分佈式事務中包含了 3 次對 db 的操做,而 3 個 db 分屬於不一樣的系統,圖中虛線覆蓋的範圍是 app1 的一個本地事務模版的代碼範圍。
來看看在 DTS 內部針對這個場景是如何實現的。 數據庫

 

 

app2 和 app3 做爲參與者分別實現了 prepare,commit 和 rollback 接口
咱們將 prepare 階段稱爲第一階段,commit/rollback 階段稱爲第二階段
上圖就是典型的 DTS 事務流轉示例,第一階段被包含在發起方的本地事務模版中,發起方的本地事務結束後,開始執行二階段操做,二階段結束,DTS 事務整個結束。
針對以上運行流程,咱們能夠總結以下
DTS 分佈式事務是基於兩階段提交( 2 phase commit,簡稱 2pc)原理
事務發起方是分佈式事務的協調者
事務發起方本地事務的最終狀態(提交或回滾)決定整個分佈式事務的最終狀態
分佈式事務必須在本地事務模板中進行
參與者經過配置在 xml 中的攔截器來完成 action 信息的獲取和數據插入
事務參與者的接口須要支持兩階段。發起方(使用者)只關注第一階段的方法,第二階段由框架自動調用。
再來看看以上的說明對應的發起方代碼是怎樣的app

 

 

 

對應的參與者接口是這樣的框架

 

 

 

最核心的地方在於 prepare 接口打上了@TwoPhaseBusinessAction 標註,經過這個標註DTS 框架能夠感知到這個服務就是一個 DTS 的參與者jvm

接下來,結合上面這個例子讓咱們詳細分析下 DTS 內部的工做原理,大致以下圖 分佈式

 

 

核心點:
使用數據庫持久化記錄事務數據,且使用獨立的事務模版,也就是單獨事務
特別關注紅線對應的 sql,這是一句 update 主事務表的 sql,而這句 sql 是在發起方的本地事務中的,這樣一來就和發起方的事務綁定了,若是發起方本地事務成功,則這句 update 語句必然成功,若是發起方本地事務失敗,則這句 update 語句必然失敗,這樣咱們就能夠根據 activity 表的事務記錄的狀態來決定這筆分佈式最終的狀態是成功仍是失敗了
在調用參與者前,啓動單獨事務插入表明這個參與者的分支事務記錄,以供後續恢復使用
二階段是經過 spring 提供的事務同步器實現的,若是發起方的本地事務失敗,則二階段自動回滾全部參與者,若是發起方的本地事務成功,則二階段自動提交全部參與者。二階段結束後,刪除全部事務記錄學習

事務恢復
學習了 DTS 的原理以後,可能你會問,若是二階段失敗會怎樣?好比須要 commit app2 和 app3,若是 commit app2 的時候斷電了,這筆事務數據是否還能正常提交?答案是確定的,經過咱們的 xts-server 這個恢復系統來保證事務必定會被提交/回滾。在某些特殊狀況下(好比斷電,jvm crash等致使分佈式事務沒有處理完就結束了),xts-server 靠持久化記錄到 db 的事務數據來完成恢復.net

恢復系統的特色
恢復系統須要配置全部參與者信息,好比參與者的名稱,全類名以及提交和回滾方法名
恢復系統須要鏈接發起方的數據庫,來獲取對應的事務數據
恢復系統是定時恢復的,每隔一分鐘從發起方的數據庫獲取一次數據
恢復系統獲取的數據都是一分鐘以前待處理的數據,這個一分鐘是一個經驗值,咱們認爲 99.9999% 的分佈式事務一分鐘就應該結束了,事實也確實如此
嵌套事務支持
在前面的典型場景裏是 A->B 單層調用的關係,隨着業務愈來愈複雜,可能會出現 A->B->C 的嵌套場景,在這個場景下,A 仍然是做爲事務的發起方,咱們把 B 稱爲嵌套參與者,C 爲普通參與者,若是所示server

 

 

 

能夠看到,一階段和二階段的調用鏈路是徹底一致的,須要注意的是對於嵌套參與者 B 來講須要 DB 資源來存放下游參與者(這裏是 C)的分支事務記錄,在 B 調用 C 的一階段的時候會記錄表明 C 的分支事務記錄,在二階段 XTS 框架在提交完 B 這個參與者以後,會撈取 B 的分支事務表,找到 C 的記錄,從而發起對 C 的二階段提交

例子
咱們假設 A 系統提供一個充值服務,調用 B 系統,B 系統再調用 C 系統完成充值,對於 A 系統發起方代碼看起來是這樣的

 

 

 

來看看 B 這個嵌套參與者的接口,和普通參與者沒什麼差異

 

 

 

看看對應的實現

 

 

 

能夠看到對應 B 參與者來講代碼裏並無什麼特殊的點,那麼 XTS 框架是如何作到在提交 B 的時候自動提交 C 的呢?答案就是攔截器,對於嵌套參與者咱們須要配置一個特殊的攔截器NestedBusinessActionInterceptor

看看 NestedBusinessActionInterceptor 的配置

 

 

 

NestedBusinessActionInterceptor 做用於 B 服務端攔截 B 的分佈式服務,和 A 系統不要緊

前面提到對於嵌套參與者須要提供 DB 資源來存儲下游的分支事務記錄,因此對於 B 系統也須要配置 BusinessActivityControlService 來讓 XTS 框架感知 B 的 DB 信息

 

 

 

總結
對於嵌套參與者的使用:

須要提供 DB 資源,來讓 XTS 框架持久化分支事務記錄配置 NestedBusinessActionInterceptor 攔截器

相關文章
相關標籤/搜索