分布式事務DTP模型
DTP模型是Distributed Transaction Processing的縮寫,DTP是一套分布式事務的規(guī)范,不同的廠商針對此規(guī)范提供實現。DTP中包含AP、RM、TM三個角色,其中:
- AP(Application Program):應用程序,就是我們使用分布式事務的應用;
- RM(Resource Manager):資源管理器,表示參與分布式事務的資源,比如數據庫,MQ等;
- TM(Transaction Manager):事務管理器,是分布式事務的協(xié)調者。
它們之間的關系如下:

在DTP模型中,AP操作RM完成事務中的數據操作,比如數據庫的更新等,在這些操作結束后,AP通過TX接口向TM發(fā)起提交事務或者回滾事務,TM通過XA協(xié)議向RMs提交或者回滾事務,XA通過兩階段提交的方式完成事務的提交或回滾。
DTP和XA的缺點:
- 缺少事務補償機制,2PC有數據不一致的風險,如果多個RM只有一部分提交成功,其它RM在提交事務時出現超時等錯誤,無法進行事務的補償,會造成數據不一致
- XA協(xié)議會導致資源的阻塞,在整個事務的過程中,RM資源會一直被事務持有,直到事務提交或回滾
- 性能非常低
- 并不是所有資源都支持XA協(xié)議,mysql5.7以前的版本對XA的支持不太好
兩階段提交(2PC)
前面說過XA協(xié)議通過兩階段提交的方式做事務的提交或回滾,兩階段提交,即將事務的提交分為兩個階段:
- 第一階段:prepare階段,用于向RM詢問事務是否可提交,至于RM如何實現prepare則完全靠RM,比如記錄redo和undo日志
- 第二階段:commit/rollback,如果所有RM的prepare執(zhí)行后都表示可以提交,則依次commit,否則依次rollback
兩階段提交的示意圖可表示如下:

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

2PC的缺點:
- 整個事務過程中,所有資源都是阻塞式持有
- 性能差
- 會有數據的不一致風險,當有部分資源提交成功部分不成功時,數據不一致
- TM容易成為邏輯單點,當TM宕機,事務狀態(tài)難以恢復
Seata對分布式事務的支持

這里先介紹三個概念:
- 全局事務:表示一次分布式事務,由TM發(fā)起
- 分支事務:每個RM都有一個事務,被稱為分支事務
- XID:全局事務的事務ID
Seata借鑒了DTP模型中的概念,并且自定義了TC(Transaction Coordinator)角色,實際上是將事務的協(xié)調者從TM中分享出來并獨立部署,TC負責全局事務的提交和回滾,并對分支事務做補償,使得即使事務提交過程各,部分分支事務成功部分失敗,也能達到最終一致
Seata支持的分布式事務的模式
AT模式
AT模式是建立在數據庫的ACID事務的基礎上的,它提供的兩階段提交是對XA的兩階段提交的演進,效率上比XA好,但是整體開銷還是偏大。AT模式的基礎原理是在每個分支事務的數據庫中記錄事務的回滾日志,seata對事務的處理過程如下:
開啟全局事務,向TC獲取事務ID
依次執(zhí)行分支事務
開啟分支事務
通過解析sql的方式拿到sql的表、更新字段、條件等
根據條件查詢,獲取到事務更新前的鏡像
執(zhí)行更新
再次查詢,獲取 到更新后的鏡像
通過后鏡像生成redo log,插入到分支事務所在的庫中
提交分支事務前,先向TC注冊分支事務,并獲取操作的數據的id對應的全局鎖,如果獲取失敗,全局鎖被其它事務持有,則回滾
提交分支事務,并向TC上報分支事務執(zhí)行結果
提交全局事務,釋放全局鎖
當事務需要回滾時,每個分支事務的DB中有redo log,RM通過redo log執(zhí)行事務的回滾,但回滾時需要對數據進行判斷,如果當前數據與redo log中的兵團鏡像相同,則回滾,否則表示數據被事務外的操作修改了,需要根據配置策略做處理。AT模式下的兩階段提交行為如下:
- 一階段 prepare 行為:在本地事務中,一并提交業(yè)務數據更新和相應回滾日志記錄。
- 二階段 commit 行為:馬上成功結束,自動 異步批量清理回滾日志。
- 二階段 rollback 行為:通過回滾日志,自動 生成補償操作,完成數據回滾
TCC模式
Seata支持TCC模式,TCC模式也是基于兩階段提交的,與AT模式不同的是,TCC不依賴數據庫的ACID特性,而是依賴應用自定義的一階段的prepare行為和二階段的commit/rollback行為,TCC模式將事務從數據庫層面提升到了應用服務層面。
在TCC模式中,分支事務需要實現prepare、commit和rollback三個方法,其示意圖如下:

總體過程比較清晰:
TM開啟全局事務,獲取XID
依次執(zhí)行分支事務
向TC注冊分支事務
執(zhí)行事務的prepare階段
提交或者回滾全局事務,TC向每個RM發(fā)起commit或者rollback
TCC模式下,兩階段行為如下:
- 一階段 prepare 行為:調用 自定義 的 prepare 邏輯。
- 二階段 commit 行為:調用 自定義 的 commit 邏輯。
- 二階段 rollback 行為:調用 自定義 的 rollback 邏輯。
Saga模式
Saga模式是SEATA提供的長事務解決方案,在Saga模式中,業(yè)務流程中每個參與者都提交本地事務,當出現某一個參與者失敗則補償前面已經成功的參與者,一階段正向服務和二階段補償服務都由業(yè)務開發(fā)實現。
說簡單點,就是第一階段,每個分支事務先自己提交,當需要回滾的時候,分支事務提供一個回滾的入口,對事務做逆向過程:

Saga模式有一定的優(yōu)勢:
- 參與者可異步執(zhí)行
- 性能高,一階段提交本地事務
- 補償服務易于實現
AT、TCC、Saga三種模式的比較
AT模式:
AT模式的性能低,有全局鎖,一次分支事務多一次SQL解析和兩次查詢一次插入,成本比本地事務高得多,這些DB操作是實現回滾的代價
全局鎖有死鎖的風險
保證了隔離性,全局鎖能實現讀隔離和寫隔離,詳情可以閱讀seata的文檔
基于本地數據庫的ACID特性,代碼改造代價低
TCC模式:
代碼改造代價大,需要將事務拆分成prepare+commit并提供rollback
性能好,不會阻塞資源
將兩階段由應用自身定義,可達到較高的隔離性
Saga模式:
代碼改造代價比TCC模式小,但比AT模式大,需要提供回滾補償接口
性能好,第一階段就提交了分支事務
沒有隔離性
AT、TCC、Saga三種模式,是在性能、改造成本、隔離性三者之間做權衡和取舍,AT選擇了隔離性和低改造成本,TCC選擇了性能和隔離性,Saga選擇了性能和低改造成本,如下圖所示:

基于事務消息的分布式事務方案
還可選擇使用RocketMQ的事務消息來實現分布式事務。
優(yōu)點:
- 實現簡單,改造成本小
- 性能高,沒有全局鎖,也沒有兩階段的開銷
同樣有缺點和限制:
- 沒有隔離性的支持
- 弱一致,對于庫存扣減類場景不適用
- 事務消息一旦提交,全局無法回滾
如果采用事務消息實現分布式事務,需要有其它方案規(guī)避其缺點,這里不做描述。