分布式消息事務解決方案選型詳解

2019-12-18     日行四善

分布式消息事務解決方案選型詳解

微服務的普及,使用隊列處理服務之間通信成為一種潮流,利用隊列消息解耦系統不可避免的會出現數據不一致問題。

產生原因

發布方問題:運行的系統無法避免的存在單點故障問題,保存本地事務和推送隊列無論是哪個先執行都無法保證這兩個一定都執行完成,先保存本地事務,服務發生故障,消息沒推送,反之同理。

訂閱方問題:消費收到消息後,執行過程中發生錯誤或宕機,導致沒執行成功。

發布方解決方案

選出兩種比較簡單的並且不同體系的產品來對比(阿里的RockMq/.net core的CAP框架),先了解下兩種方案的實現過程

.net core 的CAP框架

首先,在你項目運行時候會在你項目指定得資料庫生成一張表(cap.published)這張表是用來存儲要發送消息的日誌。消息有三個狀態(Scheduled,Succeeded,Failed),啟動程序時候同時還會啟動一個監聽程序,隔幾分鐘把表中Failed的消息重新發送。

我用下訂單來舉個詳細例子

這種設計方式相對於2PC/TCC來說,複雜性降低了一個級別,而且支持多種資料庫和消息隊列,擴展性極強,我覺得缺點應該是依賴資料庫,發布消息需要插入日誌消息到資料庫,受限於單機資料庫的瓶頸,如果分庫分表還要處理這塊,要麼就得在資料庫層面做分庫分表。CAP文檔

阿里的RocketMq

Rocketmq的功能十分強大,有普通消息,定時消息,全局/局部順序消息以及事務消息,在阿里雲可以直接買服務來使用。RocketMq的事務採用了TCC模式(Try-Confirm-Cancel)

提交mq半事務半事務消息成功確認mq事務回查事務回滾mq事務

可以簡單理解為下圖內容 【我(消息發送方)和 大佬(rocketmq服務)的聊天記錄】

1.完美成功情況

2.消息發送方宕機情況

3.消息發送方本地事務失敗情況

可以上阿里雲搜Rocketmq查看該產品使用手冊。

阿里的RocketMq 與 CAP 使用架構場景分析

CAP適合於發送隊列消息與業務在同一個服務的場景,而中台架構就不適合,因為中台架構分基礎服務和業務中台,隊列一般在業務中台跟業務掛鉤,有一個訂單基礎服務,但有N個應用中台都是調用這個訂單基礎服務存儲訂單數據,每個中台都相當於一個應用,邏輯可能差異很大,更傾向於在中台決定推不推送消息和推什麼消息,這種情況下CAP就完全不適合。

訂閱方解決方案

1. 系統突然崩潰導致丟失

系統的瞬態故障產生的問題,重試便可以解決

2. 程序出現bug導致一直重試一直失敗

這種情況重試是解決不了問題的,需要開發人員做好PlanB,重試N次不成功便執行PlanB。

3. 冪等性問題

發送端監聽重複推送導致的問題,有兩種方案可以解決。

  1. 根據業務狀態判斷,比如訂單支付完成後重複推送根據完成狀態忽略掉重複那條
  2. 執行業務邏輯前查詢該消息是否被執行過,因為重複推送消息的消息id必然是一樣的,可以根據這個消息id進行判定。

回到選中的兩大框架的消費端

CAP框架

同發送端一樣,在你項目運行時候會在你項目指定得資料庫生成一張表(cap.received)這張表是用來存儲消費的消息日誌。消息有三個狀態(Scheduled,Succeeded,Failed),啟動程序時候同時還會啟動一個監聽程序,隔幾分鐘把表中Failed的消息重消費。

發送端演示下單,消費端就來個扣庫存的。


RocketMq

訂閱消息有兩種方式:

1.通過http拉取(注意 官方的SDK的http請求性能很差,建議最好自己寫)

2.開啟tcp監聽獲取(注意 .net的TCP監聽獲取消息的SDK至今沒有Linux版本--2019年12月13)

獲取消息需要在代碼里進行ack確認

總結

CAP框架:功能單一,使用簡單,.net體系的可自行擴展,適合自治微服務架構。

RocketMq:功能豐富,維護簡單,穩定性強,但使用還需要自己做相關開發,使用成本高,對.net支持不太好,適合中台服務。


作者:Carson_dotnet
連結:https://www.jianshu.com/p/f90ce421893e

文章來源: https://twgreatdaily.com/zh-mo/D75JIW8BMH2_cNUgJeTe.html