Transactional Sagas#

Saga 的概念源於限制早期分散式架構中資料庫鎖的範圍,最早可追溯至 1987 年 ACM 會議的論文。Chris Richardson 將微服務的 saga pattern 描述為:一系列的 local transaction,每個更新發布一個事件,觸發序列中的下一個更新;若任何更新失敗,saga 會發出一系列 compensating update 來復原先前的變更。

分散式交易缺乏原子性,真正有趣的是錯誤發生時的處理。本章深入探討八種 transactional saga 模式及其取捨。

Figure 12.1: Legend for ISO architecture interaction diagrams

Transactional Saga Patterns#

三個交互維度(communication、consistency、coordination)的組合產生八種 saga 模式:

Pattern 名稱CommunicationConsistencyCoordination
Epic Saga(sao)SynchronousAtomicOrchestrated
Phone Tag Saga(sac)SynchronousAtomicChoreographed
Fairy Tale Saga(seo)SynchronousEventualOrchestrated
Time Travel Saga(sec)SynchronousEventualChoreographed
Fantasy Fiction Saga(aao)AsynchronousAtomicOrchestrated
Horror Story(aac)AsynchronousAtomicChoreographed
Parallel Saga(aeo)AsynchronousEventualOrchestrated
Anthology Saga(aec)AsynchronousEventualChoreographed

上標字母代表三個維度的值(依字母順序:communication, consistency, coordination),例如 Epic Saga(sao) 代表 synchronous, atomic, orchestrated。

Epic Saga(sao) Pattern#

最「傳統」的 saga 模式,也稱為 Orchestrated Saga,模擬單體系統的行為。

  • 使用 synchronous 通訊、atomic 一致性、orchestrated 協調
  • Orchestrator 協調包含多個服務更新的工作流程,要求全部成功或全部失敗
  • 使用 compensating update(補償更新) 來處理錯誤:反轉資料寫入操作(如復原更新、重新插入已刪除的列等)

Figure 12.2: The Epic Saga(sao) pattern's dynamic coupling

Figure 12.3: The isomorphic communication illustration of the Epic Saga(sao) pattern

Figure 12.4: A successful orchestrated transactional Epic Saga using a compensating update

Figure 12.5: When an error occurs, a mediator must send compensating requests

特性評估

項目評分
CouplingVery high
ComplexityLow
Responsiveness/availabilityLow
Scale/elasticityVery low

雖然 compensating transaction 看似乾淨的解決方案,但認識到模式存在不等於解決了問題。分散式交易充滿困難,應盡可能避免。

Phone Tag Saga(sac) Pattern#

將 Epic Saga 的 coordination 從 orchestrated 改為 choreographed

  • 初始服務成為協調點(front controller),完成工作後傳給下一個服務
  • 每個服務必須內建錯誤處理和 compensating request 的邏輯
  • 適合簡單工作流程,需要比 Epic Saga 更好的擴展性

Figure 12.6: The Phone Tag pattern utilizes loosely coupled communication

特性評估

項目評分
CouplingHigh
ComplexityHigh
Responsiveness/availabilityLow
Scale/elasticityLow

Fairy Tale Saga(seo) Pattern#

放寬了 atomic 要求,改用 eventual consistency,是許多微服務架構中常見且受歡迎的模式。

  • 使用 synchronous 通訊、eventual 一致性、orchestrated 協調
  • Orchestrator 負責協調請求、回應和錯誤處理,但不負責管理交易
  • 每個領域服務管理自己的交易行為,整體工作流程依賴最終一致性
  • 最大的吸引力在於沒有全域交易的需求

Figure 12.8: The Fairy Tale Saga(seo) illustrates eventual consistency

Figure 12.9: Isomorphic illustration of a Fairy Tale interaction

特性評估

項目評分
CouplingHigh
ComplexityVery low
Responsiveness/availabilityMedium
Scale/elasticityHigh

Fairy Tale Saga 結合了最方便的選項(orchestrated、synchronous)和最寬鬆的限制(eventual consistency),是架構師的熱門選擇。

Time Travel Saga(sec) Pattern#

使用 synchronous 通訊和 eventual consistency,但採用 choreographed 工作流程。

  • 避免中央 mediator,工作流程責任完全在參與的領域服務上
  • 可實作 Chain of Responsibility 設計模式或 Pipes and Filters 架構風格
  • 每個服務「擁有」自己的交易上下文,狀態會隨時間逐漸一致
  • 非常適合高吞吐量的 fire and forget 工作流程(如電子資料擷取、批次交易)

Figure 12.10: The Time Travel Saga(sec) pattern uses two of three decoupling techniques

Figure 12.11: Complex workflows become difficult to manage without orchestration

特性評估

項目評分
CouplingMedium
ComplexityLow
Responsiveness/availabilityMedium
Scale/elasticityHigh

Fantasy Fiction Saga(aao) Pattern#

使用 asynchronous 通訊、atomic 一致性、orchestrated 協調。

  • 看似只是將 Epic Saga 的通訊改為非同步以提升效能,但實際上增加了大量複雜度
  • 非同步通訊移除了序列假設,增加了 deadlock、race condition 等平行系統問題
  • 當多個交易工作流程同時進行且有依賴關係時,mediator 必須追蹤所有待處理交易的狀態

Figure 12.12: Asynchronous communication makes transactionality difficult

Figure 12.13: The Fantasy Fiction Saga(aao) pattern is far-fetched

Figure 12.14: The most difficult combination: achieving transactionality while asynchronous

特性評估

項目評分
CouplingHigh
ComplexityHigh
Responsiveness/availabilityLow
Scale/elasticityLow

此模式比它應有的受歡迎程度更高,通常是架構師誤以為將 Epic Saga 改為非同步即可提升效能的結果。更好的替代方案是 Parallel Saga(aeo)。

Horror Story(aac) Pattern#

最糟糕的組合之一:asynchronous 通訊 + atomic 一致性 + choreographed 協調。

  • 結合了最嚴格的耦合需求(atomic)與最鬆散的耦合風格(asynchronous + choreography)
  • 沒有 mediator 來管理跨多個服務的交易一致性
  • 每個領域服務必須追蹤多個待處理交易的 undo 資訊,且可能順序錯亂

Figure 12.15: This pattern requires a lot of interservice communication

特性評估

項目評分
CouplingMedium
ComplexityVery high
Responsiveness/availabilityLow
Scale/elasticityMedium

Horror Story 通常是架構師從 Epic Saga 出發,發現效能慢後嘗試加入 asynchronous 和 choreography 的結果,但忽略了各維度之間的糾纏。

Parallel Saga(aeo) Pattern#

以 Epic Saga 為基礎,放寬兩個限制:改用 asynchronous 通訊和 eventual 一致性。

  • 使用 mediator 協調複雜工作流程,但以非同步通訊提升回應性和平行執行
  • 每個服務維護自己的交易邊界,consistency 由各服務負責
  • 錯誤發生時,mediator 可發送非同步訊息給相關服務進行補償

Figure 12.16: Parallel Saga(aeo) offers performance improvements over traditional sagas

Figure 12.17: Each service owns its own transactionality; the mediator coordinates

特性評估

項目評分
CouplingLow
ComplexityLow
Responsiveness/availabilityHigh
Scale/elasticityHigh

Parallel Saga 對許多場景提供了有吸引力的取捨組合,特別適合需要高擴展性的複雜工作流程。

Anthology Saga(aec) Pattern#

與 Epic Saga 完全相反:使用 asynchronous 通訊、eventual 一致性、choreographed 協調,是耦合最低的模式。

  • 使用 message queue 在服務間傳遞非同步訊息,沒有 orchestrator
  • 每個服務維護自己的交易完整性,服務必須包含更多工作流程上下文
  • 沒有瓶頸或耦合節點,可實現高回應性和擴展性
  • 不適合複雜或關鍵的工作流程,因為協調極為困難
  • 可使用 stamp coupling 傳遞工作流程狀態

Figure 12.18: The Anthology Saga(aec) pattern offers the opposite extremes of the Epic Saga

Figure 12.19: Lack of orchestration, eventual consistency, and asynchronicity make this pattern difficult

特性評估

項目評分
CouplingVery low
ComplexityHigh
Responsiveness/availabilityHigh
Scale/elasticityVery high

State Management and Eventual Consistency#

狀態管理和最終一致性利用 finite state machine(有限狀態機) 來追蹤 transactional saga 的當前狀態,並透過重試或人工修復最終修正錯誤。

以 Fairy Tale Saga(seo) 實作的 ticket 完成流程為例:

  • 當 Survey Service 不可用時,saga 狀態改為 NO_SURVEY,仍回傳成功給用戶
  • Ticket Orchestrator Service 在背景非同步處理錯誤(重試或送交管理員手動處理)
  • 終端使用者不受錯誤影響,回應性更好

Saga State Machines#

State machine 描述分散式架構中所有可能的路徑,包含起始狀態、轉換狀態和對應的動作。

以 Sysops Squad 新問題單為例,狀態流程為:

Figure 12.21: State diagram for creating a new problem ticket

STARTCREATEDASSIGNEDACCEPTEDCOMPLETEDCLOSED

額外的錯誤路徑:

  • ACCEPTED → REASSIGN(專家無法修復)→ ASSIGNED
  • COMPLETED → NO_SURVEY(問卷服務不可用)→ CLOSED

將所有狀態轉換和對應動作列成表格,開發人員可據此實作 orchestrator 或各服務中的狀態轉換觸發器和錯誤條件。

State Management vs. Compensating Updates 的取捨#

優勢劣勢
良好的回應性錯誤時資料可能暫時不同步
錯誤對終端使用者影響較小最終一致性可能需要一些時間

Techniques for Managing Sagas#

分散式交易無法簡單地「引入」系統,必須經過設計、編碼和維護。

一個實用技術是使用 annotations(Java)或 custom attributes(C#)來標記服務參與的 saga:

  • 定義 @Saga annotation,包含 Transaction enum(如 NEW_TICKETCANCEL_TICKET 等)
  • 在各服務的 entry point 類別上標註所參與的 saga
  • 可撰寫 code-walking tool 自動掃描 codebase,查詢特定 saga 涉及哪些服務

這種 annotation 方式提供了以程式化方式捕獲、記錄系統中所有 transactional saga 的能力,幫助開發人員了解變更的影響範圍。

Sysops Squad Saga: Atomic Transactions and Compensating Updates#

團隊討論 Epic Saga 模式下 ticket 完成工作流程的問題:

Figure 12.22: The epic saga requires the ticket status to be updated and survey to be sent

Epic Saga 的三大挑戰#

1. 缺乏交易隔離(No Transaction Isolation)

  • 在分散式交易中沒有隔離機制,其他服務可能在交易完成前就使用了已更新的資料
  • 例如:Ticket Service 非同步發送資料給 Analytics Service(步驟 4-5),但 compensating update(步驟 7)執行時,Analytics 已處理了該資料
  • 這種 side effect 極難修復,因為下游可能有更多連鎖反應

Figure 12.23: Epic Saga(sao) requires compensation, but side effects can occur

2. Compensating Update 可能失敗

  • 假設 compensating update 一定會成功是危險的
  • 當 compensation 本身失敗時,系統處於不一致狀態,且不確定該回傳什麼給終端使用者

Figure 12.24: Compensating updates within an Epic Saga can fail

3. 回應性差

  • Atomic 分散式交易必須等待所有 corrective action 完成後才能回應使用者
  • 使用 eventual consistency(如 Fairy Tale Saga 或 Parallel Saga)可改善回應性

Compensating Updates 的取捨#

優勢劣勢
所有資料恢復至先前狀態沒有交易隔離
允許重試和重啟Compensation 時可能發生 side effect
Compensation 本身可能失敗
終端使用者回應性差

關鍵洞察#

  • 現實世界中大部分事情並非交易性的(如 Gregor Hohpe 的著名文章「Starbucks Does Not Use Two-Phase Commit」)
  • 交易協調是架構中最困難的部分之一,範圍越廣越困難
  • 更實際的方案是使用 Fairy Tale SagaParallel Saga,依賴非同步的 eventual consistency 和狀態管理,而非 atomic 分散式交易和 compensating update