iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
2
Software Development

服務開發雜談系列 第 8

微服務瞎談(8) Saga, Choreography vs Orchestration

上篇提到Saga模式.
末段的流程是把Saga的決策和執行順序的邏輯分佈在Saga的每一個參與者之中, 透過通訊交換事件的方式來溝通, 這種叫做Choreography-based saga(協同式Saga).

協同式Saga(Choreography-based saga)

Choreography是沒有一個集中協調器來各訴Saga參與方該做什麼事情, 而是Saga參與方對彼此的事件做出回應.
除了Saga之間直接透過API呼叫, 也能透過MQ做訊息投遞.

要做補償通知也是透過MQ做訊息投遞即可.

訊息傳遞

協同式Saga大部分實做都依賴MQ, 所以MQ的吞吐量和一些保證機制就非常重要了.
這部份後面講到NATS時會介紹.
這裡注意的是為了能讓Saga參與方能夠將接收到的每個事件映射到自己的資料上.
舉例: Debit服務上, 能紀錄是哪個Order來扣款的.
就必須能讓Saga參與方能夠查找到相對應的資料. 這裡會需要Saga發布方發布出去的資料需要包含關聯性ID這類的資訊, 以便其他參與方能夠方便查找.

pros

  1. 簡單: 各服務在對業務對象進行CRUD時做發布事件, 容易實做; 只要定義好資料結構, Emit到MQ即可; 接收方只要實做接收到命令的動作或是補償
  2. 鬆散耦合: 各Saga參與方所關心的事件與服務之間不會因此產生耦合.

cons

  1. 難以理解維護: 因為Saga的操作邏輯分散在每個服務內, 所以對系統不熟的同仁沒法快速理解是如何工作的; 且MQ要追蹤訊息也不容易, 也不太方便測試.
  2. 冪等性的設計考量
  3. 循環依賴的容易出現: 像上圖Order跟Account之間的第5-8步驟, 出現了循環依賴, 這是一種不好的設計風格

編排式Saga(Orchestration-based saga)

協同式Saga就像是個去中心化的概念, 現在要講的編排式Saga就是個中心化的服務來統一管理跟處理這些操作.
實做一個編排器(Orchestrator), 這個編排器是個業務Proxy類別, 唯一職責就是告訴Saga參與方該做什麼事情.

梳理一下流程, 將編排器視為一個狀態機(State Machine).

  1. 初始化訂單: 該Saga在等到Inventory驗證庫存
  2. 準備訂單: 該Saga收到Inventory回覆庫存Ok, 更改Order狀態, 並開始準備扣款
  3. Order Approved最終狀態: 收到Account的回應, 表示該Saga已經成功完成, 更新狀態

如果是庫存失敗

  1. 初始化訂單: 該Saga在等到Inventory驗證庫存
  2. Order Canceled最終狀態: 收到Inventory的回應, 表示該Saga被其中一個參與方拒絕

對於Order Saga來說, 操作就是對某Saga參與方的調用.
狀態之間的轉換, 由Order Saga執行的本地事務來觸發. 當前狀態跟本地事務的結果, 就決定了狀態轉換還有要執行的動作.

pros

  1. 相較簡單的依賴關係, 因為去除了循環依賴; 編排器會負責調用參與方, 但參與方並不會直接調用編排器.
  2. 改善關注點隔離, 簡化業務邏輯: 原本的Order類別需要去了解所有參與的Saga. 現在只要交給編排器就好
  3. 回滾補償更容易管理
  4. 方便測試
  5. 添加新步驟, 事務複雜度保持線性

cons

  1. 編排器存在集中過多的業務邏輯

事務隔離

SAGA由於沒支援隔離性, 這問題頗大條.
可能會發生,

  1. 更新丟失: 2個Saga同時操作一筆資料, 其中一個沒有讀取更新, 直接覆蓋蓋了另一個Saga所作的變更
  2. 髒讀: 1個Saga讀取了另一個Saga還沒完成的更新
  3. 模糊讀取/不可重複讀: 在一個Saga事務內, 其關心的資料被其他Saga進行了更動, 導致在此Saga中兩個不同步驟讀取相同的資料, 卻獲得不同的結果.

解法:

  1. 在應用層面加入邏輯鎖, 對這事務id上鎖, 確保操作串行化
  2. 使用樂觀鎖處理併發更新; 使用版本欄位來檢查當當前版本, 跟程式讀取聚合時的版本有沒有一致, 一致才更新
  3. 跟錢或是庫存有關的, 可以預先凍結資金或者是遇扣庫存的方式來隔離

上一篇
微服務瞎談(7) Saga Pattern
下一篇
分散式系統中的冪等性 & Unique ID
系列文
服務開發雜談33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言