分佈式事務與Seata

分佈式事務DTP模型

DTP模型是Distributed Transaction Processing的縮寫,DTP是一套分佈式事務的規範,不同的廠商針對此規範提供實現。DTP中包含AP、RM、TM三個角色,其中:

· AP(Application Program):應用程序,就是我們使用分佈式事務的應用;

· RM(Resource Manager):資源管理器,表示參與分佈式事務的資源,比如數據庫,MQ等;

· TM(Transaction Manager):事務管理器,是分佈式事務的協調者。

它們之間的關係如下:

分佈式事務與Seata

在DTP模型中,AP操作RM完成事務中的數據操作,比如數據庫的更新等,在這些操作結束後,AP通過TX接口向TM發起提交事務或者回滾事務,TM通過XA協議向RMs提交或者回滾事務,XA通過兩階段提交的方式完成事務的提交或回滾。

DTP和XA的缺點:

· 缺少事務補償機制,2PC有數據不一致的風險,如果多個RM只有一部分提交成功,其它RM在提交事務時出現超時等錯誤,無法進行事務的補償,會造成數據不一致

· XA協議會導致資源的阻塞,在整個事務的過程中,RM資源會一直被事務持有,直到事務提交或回滾

· 性能非常低

· 並不是所有資源都支持XA協議,mysql5.7以前的版本對XA的支持不太好

兩階段提交(2PC)

前面說過XA協議通過兩階段提交的方式做事務的提交或回滾,兩階段提交,即將事務的提交分為兩個階段:

· 第一階段:prepare階段,用於向RM詢問事務是否可提交,至於RM如何實現prepare則完全靠RM,比如記錄redo和undo日誌

· 第二階段:commit/rollback,如果所有RM的prepare執行後都表示可以提交,則依次commit,否則依次rollback

兩階段提交的示意圖可表示如下:

分佈式事務與Seata

如果有RM的prepare階段失敗,則需要回滾,示意圖如下:

分佈式事務與Seata

2PC的缺點:

· 整個事務過程中,所有資源都是阻塞式持有

· 性能差

· 會有數據的不一致風險,當有部分資源提交成功部分不成功時,數據不一致

· TM容易成為邏輯單點,當TM宕機,事務狀態難以恢復

Seata對分佈式事務的支持

分佈式事務與Seata

這裡先介紹三個概念:

· 全局事務:表示一次分佈式事務,由TM發起

· 分支事務:每個RM都有一個事務,被稱為分支事務

· XID:全局事務的事務ID

Seata借鑑了DTP模型中的概念,並且自定義了TC(Transaction Coordinator)角色,實際上是將事務的協調者從TM中分享出來並獨立部署,TC負責全局事務的提交和回滾,並對分支事務做補償,使得即使事務提交過程各,部分分支事務成功部分失敗,也能達到最終一致

Seata支持的分佈式事務的模式

AT模式

AT模式是建立在數據庫的ACID事務的基礎上的,它提供的兩階段提交是對XA的兩階段提交的演進,效率上比XA好,但是整體開銷還是偏大。AT模式的基礎原理是在每個分支事務的數據庫中記錄事務的回滾日誌,seata對事務的處理過程如下:

· 開啟全局事務,向TC獲取事務ID

· 依次執行分支事務

· 開啟分支事務

· 通過解析sql的方式拿到sql的表、更新字段、條件等

· 根據條件查詢,獲取到事務更新前的鏡像

· 執行更新

· 再次查詢,獲取 到更新後的鏡像

· 通過後鏡像生成redo log,插入到分支事務所在的庫中

· 提交分支事務前,先向TC註冊分支事務,並獲取操作的數據的id對應的全局鎖,如果獲取失敗,全局鎖被其它事務持有,則回滾

· 提交分支事務,並向TC上報分支事務執行結果

· 提交全局事務,釋放全局鎖

當事務需要回滾時,每個分支事務的DB中有redo log,RM通過redo log執行事務的回滾,但回滾時需要對數據進行判斷,如果當前數據與redo log中的兵團鏡像相同,則回滾,否則表示數據被事務外的操作修改了,需要根據配置策略做處理。AT模式下的兩階段提交行為如下:

· 一階段 prepare 行為:在本地事務中,一併提交業務數據更新和相應回滾日誌記錄。

· 二階段 commit 行為:馬上成功結束,自動 異步批量清理回滾日誌。

· 二階段 rollback 行為:通過回滾日誌,自動 生成補償操作,完成數據回滾

TCC模式

Seata支持TCC模式,TCC模式也是基於兩階段提交的,與AT模式不同的是,TCC不依賴數據庫的ACID特性,而是依賴應用自定義的一階段的prepare行為和二階段的commit/rollback行為,TCC模式將事務從數據庫層面提升到了應用服務層面。

在TCC模式中,分支事務需要實現prepare、commit和rollback三個方法,其示意圖如下:

分佈式事務與Seata

總體過程比較清晰:

· TM開啟全局事務,獲取XID

· 依次執行分支事務

· 向TC註冊分支事務

· 執行事務的prepare階段

· 提交或者回滾全局事務,TC向每個RM發起commit或者rollback

TCC模式下,兩階段行為如下:

· 一階段 prepare 行為:調用 自定義 的 prepare 邏輯。

· 二階段 commit 行為:調用 自定義 的 commit 邏輯。

· 二階段 rollback 行為:調用 自定義 的 rollback 邏輯。

Saga模式

Saga模式是SEATA提供的長事務解決方案,在Saga模式中,業務流程中每個參與者都提交本地事務,當出現某一個參與者失敗則補償前面已經成功的參與者,一階段正向服務和二階段補償服務都由業務開發實現。

說簡單點,就是第一階段,每個分支事務先自己提交,當需要回滾的時候,分支事務提供一個回滾的入口,對事務做逆向過程:

分佈式事務與Seata

Saga模式有一定的優勢:

· 參與者可異步執行

· 性能高,一階段提交本地事務

· 補償服務易於實現

AT、TCC、Saga三種模式的比較

· AT模式:

· AT模式的性能低,有全局鎖,一次分支事務多一次SQL解析和兩次查詢一次插入,成本比本地事務高得多,這些DB操作是實現回滾的代價

· 全局鎖有死鎖的風險

· 保證了隔離性,全局鎖能實現讀隔離和寫隔離,詳情可以閱讀seata的文檔

· 基於本地數據庫的ACID特性,代碼改造代價低

· TCC模式:

· 代碼改造代價大,需要將事務拆分成prepare+commit並提供rollback

· 性能好,不會阻塞資源

· 將兩階段由應用自身定義,可達到較高的隔離性

· Saga模式:

· 代碼改造代價比TCC模式小,但比AT模式大,需要提供回滾補償接口

· 性能好,第一階段就提交了分支事務

· 沒有隔離性

AT、TCC、Saga三種模式,是在性能、改造成本、隔離性三者之間做權衡和取捨,AT選擇了隔離性和低改造成本,TCC選擇了性能和隔離性,Saga選擇了性能和低改造成本,如下圖所示:

分佈式事務與Seata

基於事務消息的分佈式事務方案

還可選擇使用RocketMQ的事務消息來實現分佈式事務。

優點:

· 實現簡單,改造成本小

· 性能高,沒有全局鎖,也沒有兩階段的開銷

同樣有缺點和限制:

· 沒有隔離性的支持

· 弱一致,對於庫存扣減類場景不適用

· 事務消息一旦提交,全局無法回滾

如果採用事務消息實現分佈式事務,需要有其它方案規避其缺點,這裡不做描述。


分享到:


相關文章: