分布式事務與Seata

分布式事務DTP模型

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

  • AP(Application Program):應用程序,就是我們使用分布式事務的應用;
  • RM(Resource Manager):資源管理器,表示參與分布式事務的資源,比如數據庫,MQ等;
  • TM(Transaction Manager):事務管理器,是分布式事務的協(xié)調者。

它們之間的關系如下:

image

在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

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

image

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

image

2PC的缺點:

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

Seata對分布式事務的支持

image

這里先介紹三個概念:

  • 全局事務:表示一次分布式事務,由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三個方法,其示意圖如下:

image

總體過程比較清晰:

  • 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ā)實現。

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

image

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選擇了性能和低改造成本,如下圖所示:

image

基于事務消息的分布式事務方案

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

優(yōu)點:

  • 實現簡單,改造成本小
  • 性能高,沒有全局鎖,也沒有兩階段的開銷

同樣有缺點和限制:

  • 沒有隔離性的支持
  • 弱一致,對于庫存扣減類場景不適用
  • 事務消息一旦提交,全局無法回滾

如果采用事務消息實現分布式事務,需要有其它方案規(guī)避其缺點,這里不做描述。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容