1. 程式人生 > 實用技巧 >Seata分散式事務XA與AT全面解析

Seata分散式事務XA與AT全面解析

Seata 分散式事務 XA與AT

Seata 是一款開源的分散式事務解決方案,star高達17300+,社群活躍度極高,致力於在微服務架構下提供高效能和簡單易用的分散式事務服務。
注:本期分享借鑑於Seata三位PMC 清銘、煊檍、屹遠
分享人:陳健斌(funkye) github id: a364176773
介紹:
同盾科技高階開發工程師 、Seata Committer、Spring cloud alibaba contributor,、Mybatis-Plus contributor(by dynamic-datasource)

目錄

  1. XA模式是什麼?
  2. 什麼是 Seata 的事務模式?
  3. AT模式是什麼?
  4. 為什麼Seata要支援XA模式?
  5. AT與XA之間的關係;
  6. 總結;

1.XA模式是什麼?

首先正如煊檍兄所言,瞭解了什麼是XA與什麼是Seata定義的事務模式,便一目瞭然。

1.1什麼是XA

用非常官方的話來說

XA 規範 是 X/Open 組織定義的分散式事務處理(DTP,Distributed Transaction Processing)標準。

XA 規範 描述了全域性的事務管理器與區域性的資源管理器之間的介面。 XA規範 的目的是允許的多個資源(如資料庫,應用伺服器,訊息佇列等)在同一事務中訪問,這樣可以使 ACID 屬性跨越應用程式而保持有效。

XA 規範 使用兩階段提交(2PC,Two-Phase Commit)來保證所有資源同時提交或回滾任何特定的事務。

XA 規範 在上世紀 90 年代初就被提出。目前,幾乎所有主流的資料庫都對 XA 規範 提供了支援。

1.2什麼是Seata的事務模式?

Seata 定義了全域性事務的框架。
全域性事務 定義為若干 分支事務 的整體協調:
1.TM 向 TC 請求發起(Begin)、提交(Commit)、回滾(Rollback)全域性事務。
2.TM 把代表全域性事務的 XID 繫結到分支事務上。
3.RM 向 TC 註冊,把分支事務關聯到 XID 代表的全域性事務中。
4.RM 把分支事務的執行結果上報給 TC。(可選)
5.TC 傳送分支提交(Branch Commit)或分支回滾(Branch Rollback)命令給 RM。

Seata 的 全域性事務 處理過程,分為兩個階段:
執行階段 :執行 分支事務,並 保證 執行結果滿足是 可回滾的(Rollbackable) 和 持久化的(Durable)。
完成階段: 根據 執行階段 結果形成的決議,應用通過 TM 發出的全域性提交或回滾的請求給 TC,
TC 命令 RM 驅動 分支事務 進行 Commit 或 Rollback。
Seata 的所謂 事務模式 是指:執行在 Seata 全域性事務框架下的 分支事務 的行為模式。
準確地講,應該叫作 分支事務模式。
不同的 事務模式 區別在於 分支事務 使用不同的方式達到全域性事務兩個階段的目標。
即,回答以下兩個問題:
執行階段 :如何執行並 保證 執行結果滿足是 可回滾的(Rollbackable) 和 持久化的(Durable)。
完成階段: 收到 TC 的命令後,做到事務的回滾/提交

2那麼什麼是Seata XA 模式?

XA 模式:
在 Seata 定義的分散式事務框架內,利用事務資源(資料庫、訊息服務等)對 XA 協議的支援,以 XA 協議的機制來管理分支事務的一種 事務模式。
執行階段:
可回滾:業務 SQL 操作放在 XA 分支中進行,由資源對 XA 協議的支援來保證 可回滾
持久化:XA 分支完成後,執行 XA prepare,同樣,由資源對 XA 協議的支援來保證 持久化(即,之後任何意外都不會造成無法回滾的情況)
完成階段:
分支提交:執行 XA 分支的 commit
分支回滾:執行 XA 分支的 rollback

以下是XA模式在Seata所定義的事務模式下的設計模型

2.1什麼是Seata AT(TXC) 模式?

去年 1 月份,Seata 開源了 AT 模式。AT 模式是一種無侵入的分散式事務解決方案。在 AT 模式下,使用者只需關注自己的“業務 SQL”,使用者的 “業務 SQL” 作為一階段,Seata 框架會自動生成事務的二階段提交和回滾操作。

通過簡介,其實可以發現AT模式的特點,只需關注自己的業務sql,對業務無入侵的一種分散式事務模式。
那麼我們應該知道他是怎麼對業務做到無入侵的?

2.2AT 模式如何做到對業務的無侵入 ?

AT模式一階段

  • 首先,在Seata的元件中,如果你想開啟分散式事務,那麼就應該在你的業務入口或者事務發起入口加上@GlobalTransactional註解
  • 如果你是AT模式就要做好資料來源代理(seata1.0後全面支援自動代理),並被sqlsessionfactroy使用(或者直接jdbc操作使用被代理資料來源)

可以發現比較關鍵的非同步,與其他模式的區別便是代理資料來源,而代理資料來源又有什麼奧祕呢?

在這裡插入圖片描述
如上圖所示,你的資料來源被代理後,通過被DataSourceProxy代理後,你所執行的sql,會被提取,解析,儲存前映象後,再執行業務sql,再儲存後鏡像,以便與後續出現異常,進行二階段的回滾操作。

2.3 AT 模式如何保證隔離性

首先我們拿到官網所展示的文件來更直觀的描述:

可以通過上圖得出:

一階段本地事務提交前,需要確保先拿到 全域性鎖 。

拿不到 全域性鎖 ,不能提交本地事務。

拿 全域性鎖 的嘗試被限制在一定範圍內,超出範圍將放棄,並回滾本地事務,釋放本地鎖。

兩個全域性事務 tx1 和 tx2,分別對 a 表的 m 欄位進行更新操作,m 的初始值 1000。

tx1 先開始,開啟本地事務,拿到本地鎖,更新操作 m = 1000 - 100 = 900。

本地事務提交前,先拿到該記錄的 全域性鎖 ,本地提交釋放本地鎖。

tx2 後開始,開啟本地事務,拿到本地鎖,更新操作 m = 900 - 100 = 800。

本地事務提交前,嘗試拿該記錄的 全域性鎖 ,tx1 全域性提交前,

該記錄的全域性鎖被 tx1 持有,tx2 需要重試等待 全域性鎖 ,如tx2等待所超時,那麼tx2便回滾本地事務所以他不會產生髒資料。

AT 模式二階段提交

二階段如果是提交的話,因為“業務 SQL”在一階段已經提交至資料庫,
所以 Seata 框架只需將一階段儲存的快照資料和行鎖刪掉,完成資料清理即可。

AT 模式二階段回滾

二階段如果是回滾的話,Seata 就需要回滾一階段已經執行的“業務 SQL”,還原業務資料。
回滾方式便是用“before image”還原業務資料;但在還原前要首先要校驗髒寫,
對比“資料庫當前業務資料”和 “after image”,
如果兩份資料完全一致就說明沒有髒寫,可以還原業務資料,如果不一致就說明有髒寫,
出現髒寫就需要轉人工處理。


完整的AT在Seata所制定的事務模式下的模型圖:

3.為什麼支援XA?

首先我們應該從AT去做判斷,為什麼Seata有了AT模式還去做XA的支援

  • 從視角出發:
    首先,我們來總結下AT模式,首先所有的事物發起,都是從TM(不僅AT)
    且資料的讀已提交只能在應用中見效(使用者自行開發的系統),對資源的檢視,無法做到全方面
    而XA可讓資源也感知到自身已處於全域性事務中,對資源的隔離性可由資料庫本身來實現,滿足
    全域性一致性
  • 從入侵性,資料庫支援角度:
    業務無入侵的更徹底,少於2個服務的操作,僅使用本地事務即可滿足一致性,而AT需要
    全域性鎖來保證隔離性,所以無論是1個服務,單庫的操作,還是n個服務都需要開啟全域性事務來保證
    隔離性。
    對資料庫的支援,如果AT需要支援mysql,pgsql,oracle以外的資料庫,需要做適配,並且
    對複雜sql的解析成本更大,開發效率低,支援的sql數量少,XA可全方位支援資料庫的sql語句
    多語言支援,如果你有java應用已經使用了seata xa那麼本地資料庫已經幫我們保證了隔離
    性,即便其餘seata不支援的語言和java並行處理下,資料也不會出現不一致的情況。

4.為什麼Seata要支援XA模式?

  • 資料鎖定:在整個事務處理過程結束前,涉及資料都被鎖定,讀寫都按隔離級別的定義約束起來。

    AT 模式使用 全域性鎖 保障基本的 寫隔離,實際上也是鎖定資料的,只不過鎖在 TC 側集中管理 解鎖效率高且沒有阻塞的問題。

  • 死鎖(協議阻塞): XA prepare 後,分支事務進入阻塞階段,收到 XA commit 或 XA rollback 前必須阻塞等待。
    如果沒有一個靠譜的協調者存在,比如abc三個庫的資料被二階段決議為提交,此時ab收到的指令,提交後,c庫在收到指令後掛了,並沒有提交xa事務,或者協調者沒有做到二階段重試,那麼這個沒有提交的xa事務將會一直 持有鎖,造成死鎖的局面

  • 效能差:效能的損耗主要來自兩個方面:一方面,事務協調過程,增加單個事務的 RT;另一方面,併發事務數 據的鎖衝突,降低吞吐。
    其實主要原因就是上面的阻塞跟資料鎖定造成,因為xa的一階段並非提交,如果一階段都是提交的場景下,由於At模式的一階段提交,at的效能是優於xa,因為它鎖在tc一側集中釋放,無需多個庫進行本地的鎖釋放

AT與XA的關係

首先,我們要明確,無論是AT還是XA,他們都是有利用到資料庫自帶的事務特性,來保證資料一致性和隔離性

比如AT一階段提交和二階段回滾,都是執行了本地事務。
比如XA的一階段和二階段,也都是利用了資料庫本身的事務特性

那麼這樣一樣我們是否應該在資料庫層面進行挖掘,AT與XA的關係呢?

首先這個時候,我們肯定要從中找相同,與找不同。AT首當其衝,他有個必須品,也就是undolog表,undolog,相
信瞭解資料庫的同學肯定是知道。
資料庫有六種日誌分別是:
重做日誌(redo log)、回滾日誌(undo log)、二進位制日誌(binlog)、錯誤日誌(errorlog)、
慢查詢日誌(slow query log)、一般查詢日誌(general log),中繼日誌(relay log)

那麼資料庫的undolog是做什麼用的呢?
undolog儲存了事務發生之前的資料的一個版本,可以用於回滾,同時可以提供多版本併發控制下的讀(MVCC)

可以發現數據庫的undolog跟seata at模式的undolog的作用不謀而合,所以可以判斷,at模式的undolog就是把本地事務作用中的undolog,利用他的原理,做到了分散式事務中,來保證了分散式事務下的事務一致性。

那麼說完了undolog,redolog呢?

Redolog的作用便是防止在發生故障的時間點,尚有髒頁未寫入磁碟,在重啟mysql服務的時候,根據redo log進行
重做,從而達到事務的永續性這一特性。

那麼為什麼Seata AT模式沒有看到redolog的存在?其實很簡單,這個redolog被隱藏的很深,也就是AT模式的一階段提交,讓資料庫作為我們的redolog,保證一階段的資料準確落盤。

這個時候是不是會想到LCN事務模式?他的undolog由資料庫來保證,缺少了一個redolog的存在。
其實大可不必思念LCN事務,解析到這裡,如果把AT改為一階段不提交,二階段提交時,前映象便是undolog,後鏡像便是redolog,也就是說AT其實就是一個不在資料庫層面,按照資料庫事務思想和實現原理的方式,做到了分散式中的事務一致性。

這時候講到這裡,XA跟AT的關係應該一幕瞭然了,準確的說,其實應該說是分散式事務跟資料庫本地事務的關係,可以說XA的缺點造成了AT模式的出生,鎖在多側(多個庫),資源阻塞,效能差。

而AT就像為了把事務的實現決定權從資料庫手中,放到了Seata中,自實現sql解析,自實現undolog(redolog),既然我們沒有
辦法去直接優化資料庫在分散式事務下的問題,那麼不如創造一個新的模式,去其糟粕,取其精華。

總結

在當前的技術發展中,目前分散式事務就是屬於扮演東風的角色,大量的分散式,微服務化,帶來的效能提
升非常明顯,但是卻缺少一個有利的保障,我相信Seata就是承擔著這樣的一個角色,讓萬事俱備不欠東風。
Seata專案的最核心的價值在於:

構建一個全面解決分散式事務問題的 標準化 平臺。

基於 Seata,上層應用架構可以根據實際場景的需求,靈活選擇合適的分散式事務解決方案。