分散式事務之最終一致性實現方案

新亮筆記發表於2021-08-21

前言

這篇文章是《關於分散式事務的理解》的後續篇:分散式事務之最終一致性實現方案。

還是那個電商需求,一個訂單支付完成後的業務場景,有如下操作:

  1. 更改訂單的狀態為 “已支付”
  2. 扣減商品庫存
  3. 給會員增加積分
  4. 建立出庫單通知倉庫發貨

我們們使用 最終一致性方案 去實現它。

什麼是最終一致性?

從字面上看就是 保證資料最後的一致性 就可以了。

為了減少系統代價,如果中間節點處理失敗,其他節點一般不會自動回滾,而是通過重試機制和人工參與的方式對失敗資料進行處理,從而來保證資料最後的一致性。

實現方案

使用 本地訊息表 + 後臺任務 + 訊息佇列 + 介面冪等性。

本地訊息表:在對應業務資料庫中增加的本地訊息表,這張表儲存業務產生的訊息,通過 本地事務 保證業務資料和訊息資料的一致性,比如:msg_publishedmsg_received 表示釋出訊息表和接收訊息表,在訊息表中會有一個狀態來標識業務是否執行成功。

後臺任務:當訊息表中有執行失敗的業務資訊時,後臺任務就會按照配置的重試策略進行重試,例如重試策略為當傳送和消費訊息的過程中失敗會立即重試 3 次,在 3 次以後將進入重試輪詢;重試將在傳送和消費訊息失敗的 4分鐘後 開始,這是為了避免設定訊息狀態延遲導致可能出現的問題;後續就會每隔 1 分鐘之後重試一次,預設的最高重試次數為 50 次,當達到 50 次時,就不會重試了,通過發郵件/微信/釘釘/簡訊的方式通知人工去處理,通知時需要考慮訊息降噪。

訊息佇列:跨服務之間的呼叫使用訊息佇列,來實現服務解耦。

介面冪等性:介面需要保證同一操作發起的一次請求或者多次請求的結果必須是一致的。

程式碼實現

推薦一個 C# 開源專案 CAP,大家可以參考一下。

這個專案只支援 C# 程式碼去整合,如果是其他語言可以參考其設計思路,然後進行一個簡單的實現。

小結

本文純屬拋磚引玉,有問題,歡迎批評指正。

你有更好的實現方案嗎?歡迎留言~

推薦閱讀

相關文章