微服務間的資料一致性(2)-OutBox Pattern
在微服務的世界我們常會以 Kafka 、MQTT 等等的 Message Broker 當作各服務之間的溝通橋樑,通常我們的使用場景會是 Service A 做完一系列操作後需要將資料儲存至 DB 然後在透過 Message Broker 呼叫接下來的 Service 。
舉個例子,用戶下定後 Order Service 建立新的訂單然後存入 DB 並傳送訂單建立的 Event
這種情形你可能訊息送到了 Kafka 但在 Commit 的時候發生了問題,導致訊息送出去了但 DB 裡卻沒資料
是不是可以改成先確定 Commit 成功在送 Kafka ?
這種情況也有可能導致 Kafka 訊息可能因為 Queue 本身不存在或是其他因素導致 DB 內有資料了,但我的 Event 卻沒送出去。
OutBox Pattern 就是為了解決這種情形而出現的
OutBox Pattern 是在 DB 裡建立一個名為 OutBox 的 table 並將建立訂單的 Event 與原先要存入 DB 的資料放在同一個 Teansaction 裡一同存入 DB。
在由 Broker 或是中間人的角色去將 OutBox table 內的 Event 讀出來送至 Kafka,這樣只要一開始 Commit 成功就可確保 Event 和 Order 都有一同被存入,就算失敗了也一起 Rollback。
OutBox Pattern 主要也有兩種實做方式,分別為 Transaction log tailing 和 Polling publisher
Transaction log tailing
又稱為 Change Data Capture (CDC),主要是依靠資料庫內部的 transaction log 一般來說資料庫只要有數據異動都會有 Log 紀錄,而 CDC 就是根據這特性抓取異動資料庫的資訊並送至 Kafka,以上面架構來說就不會有 Event Handler 而是 Kafka 直接連接 DB。
Polling publisher
就如同架構圖會有一個 Event Handler 的角色,定期去讀取 outbox table 內的資料,並將訊息送至 Kafka但請注意由於是主動去讀取 DB 的資料為了確保 Event 的順序,在 Query 的時候需要將 Event 依照時間序列做排序。
若系統是屬於分散式架構或是有多個 instance 則需要利用 Lock 。