如果你還不知道SAGA,那這篇不容錯過!|分散式事務系列(五)

碼農談IT發表於2023-05-11

來源:後端開發技術


這是分散式事務系列的第五篇,如果之前文章沒讀請自行前往。精華專題,強烈建議收藏。

‍本文詳細講解了分散式事務解決方案——SAGA。

SAGA事務

什麼是SAGA事務

SAGA 的意思是“長篇故事、長篇記敘、一長串事件”。SAGA 事務模式的提出非常早,甚至早於分散式事務概念的提出。

SAGA 於 1987 年由普林斯頓大學的 Hector Garcia-Molina 和 Kenneth Salem 在 ACM 發表的論文《SAGAS》中提出。

如果你還不知道SAGA,那這篇不容錯過!|分散式事務系列(五)

這篇論文講述的核心是如何處理長時間活躍的事務,SAGA 指出可將其拆分成可以交錯執行的子事務集合,每個子事務都是一個真實的事務,子事務可以獨自保證資料一致性。

為什麼需要SAGA

之前我們介紹了 TCC 分散式事務解決方案,它擁有諸多優點:更強的一致性、更強的個理性、更好的效能,但是他也有一個顯著的缺點就是業務侵入性強。業務侵入性強並不只是說我們編碼麻煩而已,有時候業務不是你想侵入就侵入的,比如其他部門不願意配合,比如使用三方系統。

依舊是以我們熟悉的電商業務為例子,需要經過下單、餘額支付、庫存扣件這三個過程,之前我們已經用TCC實現了這個過程。假設現在新增一個業務場景,餘額支付需要替換為直接使用繫結的銀行卡付款,現在又怎麼做?銀行並不像是我們的自有系統一樣,可以提供專門的介面供我們去將本次事務所需的資源佔用、資源提交、以及資源回滾。

如果不能用TCC,怎麼辦?這種情況下,SAGA 就有了用武之地。

SAGA 內容

SAGA 基本協議內容如下:

  • 每個 SAGA 事務都由一系列的有序子事務(sub-transaction) T1,T2,…,Ti,…,Tn組成,每個事務都支援冪等。
  • 每個 Ti 都有對應的補償動作Ci,比如 C1,C2,…,Ci,…,Cn,補償動作用於撤銷 T1,T2,…,Ti,…,Tn造成的影響。同樣,補償操作也需要支援冪等。
如果你還不知道SAGA,那這篇不容錯過!|分散式事務系列(五)

如果 T1 到 Tn 均成功提交,那麼事務就順利完成。只有有一個環節出現失敗就要採取恢復策略。

恢復策略分為向前恢復向後恢復兩種,具體使用那種方案需要根據實際場景選擇。

向前恢復(Forward Recovery)

如果某個環節的Ti事務提交失敗,那麼就對這個 Ti 事務不斷進行重試(介面要冪等),直到介面返回成功。

正向恢復不需要對應的補償動作Ci,適用於在業務上都為正向操作的場景。繼續以電商為例,如果使用者的訂單付款成功,那就一定要發貨。

順序為 T1、T2、T3 (失敗,不斷嘗試,繼續執行)、T4……

如下圖:

如果你還不知道SAGA,那這篇不容錯過!|分散式事務系列(五)

向後恢復(Backward Recovery)

如果某個環節的Ti事務提交失敗,那麼就執行這個 Ti 事務對應的補償Ci操作,不斷進行重試(Ci介面要冪等),直到介面返回成功。

這裡要求 Ci 必須可以執行成功,適用於在業務上允許失敗的場景。繼續以電商為例,如果使用者的訂單支付失敗,那麼需要支付、訂單和庫存都執行補償。

順序為 T1、T2、T3(失敗)、C3、C2、C1

如下圖:

如果你還不知道SAGA,那這篇不容錯過!|分散式事務系列(五)

實現SAGA

實現SAGA注意事項

如果實現SAGA,有三個需要注意的點:

  1. Ti和Ci是冪等的,因為都需要重試以保證最終一致性。
  2. Ci 必須是能夠成功的,否則SAGA將無法撤銷影響,如果無法成功則需要人工介入做補償。
  3. Ti 和Ci的執行順序可以交換,不保證Ti一定在Ci前執行,但是最終執行效果相同,即子事務Ti影響被撤銷。

這裡著重說一下第三點,為什麼要求Ci可以在Ti之前執行?因為網路之間的不穩定性,無法保證Ti一定執行,或者一定在Ci之前執行。具體來說,有以下三種執行情況。

  1. 正常情況:Ti先執行,Ci後執行。
  2. Ti請求因為網路問題丟失了,徹底不會執行。
  3. Ti執行超時,判斷為執行失敗,直到Ci執行前 Ti 都沒有執行完成,導致出現Ci先執行的情況。

所以,有了第三點的要求,Ti 和 Ci 順序可交換。

兩種模式

透過閱讀SAGA協議的具體內容,我們可以發現,實現的關鍵之一子事務之間的協調。首先我們要知道一個事務的開始,並且可以讓子事務按順序執行,並且在某個事務執行完後通知下一個子事務。如果有子事務執行失敗,需要按照順序執行補償邏輯。

所以根據協調子事務的方法,可以分為兩類:命令協調模式和事件編排模式。

  • 編排(Choreography):
  • 控制(Orchestration):

命令協調模式(Orchestration)

命令協調模式:由中央協調器集中處理事件的決策和業務邏輯排序,以命令或者回復的方式與每個參與服務進行通訊,全權負責告訴每個參與者什麼時候該做什麼。

如果你還不知道SAGA,那這篇不容錯過!|分散式事務系列(五)

依舊以之前的電商為例:

  1. 事務發起者呼叫SAGA控制器開啟事務(這裡的控制器也可以由發起者兼任)。
  2. SAGA中央協調器發起扣減庫存,庫存扣減結果返回。
  3. SAGA中央協調器發起建立訂單,訂單建立結果返回。
  4. SAGA中央協調器發起支付請求,支付結果返回。
  5. SAGA中央協調器處理最終結果,並返回給應用程式。

SAGA中央協調器預先知道完整的事務處理流程,這可以透過配置實現。如果任意子事務失敗失敗,它便向每個參與者傳送命令來執行補償操作Ci(或者執行重試-向前恢復)。

其缺點很明顯,既然有中央協調器就會有單點問題。

如果你還不知道SAGA,那這篇不容錯過!|分散式事務系列(五)

但是優點也很多,主要有:服務之間的編排順序明確,依賴關係簡單,不會有迴圈依賴;耦合相對較少,參與者只需要依賴協調者介面,參與者之間沒有直接依賴;參與者只需要關注自身業務,服務之間協調統一由協調器管理。

事件編排模式

事件編排模式:SAGA 中的參與者透過交換事件進行溝通,按照提前編排好的釋出順序決策和排序。

這種模式沒有單點風險,由每個服務監聽對應事件,並對事件做出反應。SAGA事務由應用程式釋出第一個事件開始,中間服務接受到對應事件做本地事務的處理,然後繼續釋出事件。每一個事件由一個或者多個服務監聽。當最後一個服務執行本地事務併發布事件後,Application 收到最後一個事件,事務結束,事件處理的順序都是提前編排好的。具體參考下圖:

如果你還不知道SAGA,那這篇不容錯過!|分散式事務系列(五)

電商訂單的例子為例:

  1. 應用程式發起SAGA事務,以訂單事件釋出開始。
  2. 庫存服務監聽開始訂單事件,扣減庫存,成功後釋出庫存扣減事件。
  3. 訂單服務監聽庫存扣減事件,建立訂單,併發布訂單已建立事件。
  4. 支付服務監聽訂單建立事件,進行支付,併發布訂單已支付事件。
  5. 應用程式監聽支付成功事件,SAGA事務結束。

事件/編排是實現 SAGA 模式的自然方式,它透過事件串聯各個服務,實現了服務之間的松耦合。並且實現簡單,只需要在執行本地事務時釋出事件。如果事務涉及 2 至 4 個步驟,則可能是非常合適的。

但是有一些缺點:因為程式碼中沒有明顯的編排邏輯,所以可能會比較難理解;服務之間可能會有迴圈依賴;因為需要訂閱事件,所以隨著服務的變更可能有漏定的風險,每次需要明確評估影響,保持下游業務訂閱的完整性。

SAGA 實踐

SAGA 使用條件

SAGA 的使用上有一些限制條件:

  1. SAGA 只允許兩個層次的巢狀,頂級的 SAGA 事務和簡單子事務。
  2. 每個子事務之間是獨立的,各自保證原子性。
  3. 全域性SAGA之間無法保證隔離性。
  4. 補償事務Ci只能從語義或者業務角度撤消了事務Ti的行為,但未必能將資料庫返回到執行Ti時的狀態。

關於補償,說明一下。比如使用者使用了紅包來支付,但是部分訂單退款,這時候我們無法補發原價值的紅包。但是我們可以在業務上進行補償,比如重新拍發一個對應退款金額的新紅包。

ACID特性保證

SAGA 不提供ACID保證,因為原子性和隔離性不能得到滿足,具體如下。

  • 原子性(Atomicity):只能業務上保證,不是嚴格的原子性。
  • 隔離性(Isolation):不能保證,不同SAGA事務之間中間結果可見。
  • 一致性(Consistency):保證最終一致性,但是中間狀態會不一致。
  • 永續性(Durability):可以保證。

TCC對比

  1. 看起來和TCC很相似,但是和TCC相比,SAGA 沒有“預留”動作,每個子事務的 T 操作直接提交資料。
  2. 因為沒有預留資料,所欲 TCC 可以保證隔離性,但是 SAGA不行。
  3. 但也因為沒有預留動作,SAGA 在一些場景下實現簡單,並且少一次網路通訊過程。
  4. SAGA適合無法提供 Try 介面的場景(比如對接銀行),這點TCC無法做到。

適用場景

  • 事務參與者含第三方或者無法提供TCC預留介面。

  • 事務流程長,涉及系統多。

  • 常用於銀行、金融、貸款,或者技術架構不統一的複雜分散式場景。

優缺點

優點:

  • 效能較高,無需鎖定資源,子事務直接提交。

  • 採用事件驅動模式,吞吐量更高。

缺點:

  1. 無法提供原子性和隔離性保證。
  2. 有一定業務侵入性,逆向介面不一定好實現。
  3. 如果採用命令協調模式有單點風險,需要做好日誌記錄和重試。

最後,歡迎大家提問和交流。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024924/viewspace-2951467/,如需轉載,請註明出處,否則將追究法律責任。

相關文章