Saga 分散式交易模式

Azure

透過協調多個服務間的一連串本地交易,維持分散式系統的資料一致性。 每個服務執行其操作並透過事件或訊息觸發下一步。 若步驟失敗,一連串補償交易會撤銷完成步驟所做的變更。

內容和問題

交易 代表可包含多個作業的工作單位。 在交易中,事件 是指影響實體的狀態變更。 命令 封裝執行動作或觸發後續事件所需的所有資訊。

交易必須遵循原子性、一致性、隔離性和持久性(ACID)原則。

  • 原子性: 所有操作要麼全部成功,要麼全部不成功。
  • 一致性: 數據會從一個有效狀態轉換成另一個有效狀態。
  • 隔離: 並行交易會產生與循序交易相同的結果。
  • 持久性:即使發生失敗, 變更在認可之後仍會保存。

在單一服務中,交易會遵循 ACID 原則,因為它們會在單一資料庫內運作。 不過,在多個服務之間達成 ACID 合規性可能更為複雜。

微服務架構中的挑戰

微服務架構通常會將 專用資料庫指派給每個微服務。 此方法提供數個優點:

  • 每個服務都會封裝自己的數據。
  • 每個服務都可以針對其特定需求使用最適合的資料庫技術和架構。
  • 每個服務的資料庫都可以獨立調整。
  • 一個服務中的失敗會與其他服務隔離。

儘管有這些優點,但此架構會使跨服務數據一致性複雜化。 傳統資料庫保證,例如 ACID 無法直接適用於多個獨立管理的數據存放區。 由於這些限制,依賴進程間通訊的架構,或傳統交易模型,例如兩階段認可通訊協定,通常更適合Saga模式。

解決方案

Saga 模式會藉由將交易拆分為一系列 本機交易 來管理交易。

顯示傳奇概觀的圖表。

每筆本機交易:

  1. 在單一服務內以原子方式完成其工作。
  2. 更新服務的資料庫。
  3. 透過事件或訊息起始下一個交易。

如果本地交易失敗,Saga 會執行一系列的 補償交易,以撤銷先前本地交易所做的變更。

Saga 模式中的重要概念

  • 可補償交易可以透過其他具有相反效果的交易加以撤銷或補償。 如果傳奇中的步驟失敗,補償交易會復原可補償交易所做的變更。

  • 樞紐交易在整個歷程中是無法回頭的轉折點。 樞紐交易成功之後,可補償的交易就不再相關。 系統必須完成所有後續的動作,才能達到一致的最終狀態。 根據傳奇的流程,樞紐交易可以承擔不同的角色:

    • 不可逆或無法補償的交易無法還原或重試。

    • 可逆和認可的 之間的界限表示樞紐交易可以是最後一個可復原或可補償的交易。 或者,它也可以是 Saga 中第一個可重試的操作。

  • 可重試交易位於樞紐交易之後。 可重試的交易具冪等性,並有助於確保 Saga 即使發生暫時性失敗,仍能到達最終狀態。 它們有助於讓 Saga 最終達到一致狀態。

Saga 實作方法

兩種典型的 Saga 實作方式是 編舞 和 協調。 每個方法都有自己的一組挑戰和技術來協調工作流程。

編舞

在編舞方法中,服務會在沒有集中式控制器的情況下交換事件。 在編舞模式中,每個本地交易都會發佈網域事件,進而觸發其他服務中的本地交易。

使用編舞顯示傳奇的圖表。

編舞的優點 編舞的缺點
適用於少數服務且不需要協調邏輯的簡單工作流程。 當您新增步驟時,工作流程可能會造成混淆。 很難追蹤每個 Saga 參與者各自會回應哪些命令。
協調不需要其他服務。 Saga 參與者之間存在循環相依的風險,因為它們必須處理彼此的命令。
不會造成單點故障,因為職責分散在 Saga 的參與者之間。 整合測試很困難,因為所有服務都必須執行以模擬交易。

協調

在協調流程中,集中式控制器或 協調器,會處理所有交易,並告知參與者根據事件執行哪些作業。 協調器會執行 Saga 請求、儲存並解讀每項任務的狀態,並透過補償交易來處理失敗復原。

使用協調流程顯示傳奇的圖表。

流程協調的優勢 編排的缺點
更適合複雜的工作流程,或當您新增服務時。 其他設計複雜度需要協調邏輯的實作。
避免迴圈相依性,因為協調器會管理流程。 因為協調器負責管理整個工作流程,所以會引入單點故障。
清楚區分責任可簡化服務邏輯。

問題和考慮

當您決定如何實作此模式時,請考慮下列幾點:

  • 設計思維轉變: 採用傳奇模式需要不同的心態。 它需要您專注於跨多個微服務的交易協調和數據一致性。

  • Saga 偵錯的複雜性: 偵錯 Saga 可能相當複雜,尤其是隨著參與的服務數量增加。

  • 不可逆的本地資料庫變更:資料無法回復,因為 Saga 參與者會將變更提交到各自的資料庫。

  • 處理暫時性失敗和等冪: 當重複相同的作業不會改變結果時,系統必須有效處理暫時性失敗並確保等冪性。 欲了解更多資訊,請參閱 冪能消費者模式。

  • 需要監控和追蹤 Saga: 監控和追蹤 Saga 的工作流程,是維持營運可視性的重要工作。

  • 補償交易的限制: 補償交易可能不一定成功,這可能會使系統處於不一致的狀態。

傳奇中潛在的數據異常

資料異常是指當 Saga 跨多個服務執行時可能發生的不一致情況。 因為每個服務都會管理自己的數據,稱為 參與者數據,因此不會跨服務進行內建隔離。 此設定可能會導致數據不一致或持久性問題,例如部分套用的更新或服務之間的衝突。 一般問題包括:

  • 遺失的更新: 當某個傳奇修改數據而不考慮另一個傳奇所做的變更時,會導致覆寫或遺失更新。

  • 髒讀: 當某個 Saga 或事務讀取了另一個 Saga 已修改、但該修改尚未完成的資料。

  • 模糊讀或不可重複讀: 當 Saga 中的不同步驟讀取到不一致的資料時,這是因為兩次讀取之間發生了更新。

解決數據異常的策略

若要減少或防止這些異常狀況,請考慮下列對策:

  • 語義鎖定: 當 Saga 的可補償交易使用信號量來表示更新正在進行時,請使用應用程式層級鎖。

  • 可交換更新: 將更新設計為可依任意順序套用,且仍得到相同結果。 這種方法有助於減少傳奇之間的衝突。

  • 悲觀觀點: 重新安排 Saga 的順序,讓資料更新在可重試的交易中進行,以消除髒讀。 否則,一個傳奇可以讀取髒數據,或 未認可的變更,而另一個傳奇同時執行可補償的交易來回復其更新。

  • 重新讀取值: 確認數據在您進行更新之前會維持不變。 如果資料有變動,請停止目前步驟,並視需要重新啟動 Saga。

  • 版本檔案: 維護記錄上執行之所有作業的記錄檔,並確保它們是以正確的順序執行,以防止衝突。

  • 根據價值採用風險導向的並行控制: 根據潛在的業務風險,動態選擇適當的並行控制機制。 例如,針對低風險更新使用sagas,以及針對高風險更新使用分散式交易。

使用此模式的時機

當下列情況時,請使用此模式:

  • 您必須確保分散式系統中的數據一致性,而不需要緊密結合。
  • 如果序列中的某個作業失敗,您需要回復或補償。

當下列情況時,此模式可能不適合:

  • 交易緊密耦合。
  • 補償交易會發生在較早的參與者身上。
  • 有迴圈相依性。

下一步

當您實作此模式時,下列模式可能相關:

  • 編舞模式 讓系統的每個元件都參與商務交易工作流程的決策程式,而不是依賴控制中心點。

  • 補償交易模式 會撤銷一系列步驟已執行的工作,並在一個或多個步驟失敗時,最終讓整體作業達到一致狀態。 實作複雜商務程式和工作流程的雲端裝載應用程式通常會遵循此 最終一致性模型。

  • 重試模式 可讓應用程式在嘗試連線至服務或網路資源時,藉由以透明方式重試失敗的作業來處理暫時性故障。 此模式可以改善應用程式的穩定性。

  • 斷路器模式可用來處理當您連線到遠端服務或資源時,復原所需時間長短不一的故障。 此模式可以改善應用程式的穩定性和復原能力。

  • 健康情況端點監視模式會在應用程式中實作功能檢查機制,讓外部工具能夠定期透過公開端點存取這些檢查。 此模式可協助您驗證應用程式和服務是否正常執行。