分散式事務解決方案(二)【基於可靠訊息的最終一致性】
2. 最終一致性(基於可靠訊息)
2.1 訊息傳送的一致性
- 指產生訊息的業務動作與訊息傳送的一致。(也就是說,如果業務操作成功,那麼由這個業務操作所產生的訊息一定要成功投遞出去,否則就丟訊息)
2.1.1 如何保障訊息傳送一致性
- 處理方式1
- 如果業務操作成功,執行訊息傳送前應用故障,訊息發不出去,導致訊息丟失(訂單系統與會計系統的資料不一致);
- 如果業務操作成功,應用正常,但訊息系統故障或網路故障,也會導致訊息發不出去(訂單系統與會計系統的資料不一致);
/** 支付訂單處理 **/
public void completeOrder() {
// 訂單處理(業務操作)
orderBiz.process();
// 傳送會記原始憑證訊息(傳送訊息)
sendAccountingVoucherMsg ();
}
- 處理方式2
- 這種情況下,更不可控,訊息發出去了,但業務可能會失敗(訂單系統與會計系統的資料不一致)
/** 支付訂單處理 **/
public void completeOrder() {
// 傳送會記原始憑證訊息(傳送訊息)
sendAccountingVoucherMsg ();
// 訂單處理(業務操作)
orderBiz.process();
}
2.1.2 正向流程
- 主動方應用先把訊息發給訊息中介軟體,訊息狀態標記為“待確認”;
- 訊息中介軟體收到訊息後,把訊息持久化到訊息儲存中,但並不向被動方應用投遞訊息;
- 訊息中介軟體返回訊息持久化結果(成功/失敗),主動方應用根據返回結果進行判斷如何進行業務操作處理:
- 失敗:放棄業務操作處理,結束(必要時向上層返回失敗結果);
- 成功:執行業務操作處理;
- 業務操作完成後,把業務操作結果(成功/失敗)傳送給訊息中介軟體;
- 訊息中介軟體收到業務操作結果後,根據業務結果進行處理;
- 失敗:刪除訊息儲存中的訊息,結束;
- 成功:更新訊息儲存中的訊息狀態為“待傳送(可傳送)”,緊接著執行訊息投遞;
- 前面的正向流程都成功後,向被動方應用投遞訊息
2.1.3 異常流程
- 異常點分析(任何一個環節都可能會出問題)
- 從主動方應用的角度Fenix
異常狀況 | 可能的狀態 | 一致性 |
---|---|---|
預傳送訊息失敗 | 訊息未進儲存,業務操作未執行(可能的原因:主動方應用、網路、訊息中介軟體、訊息儲存) | 一致 |
預傳送訊息後,主動方應用沒有收到返回訊息儲存結果 | (1)訊息未進儲存,業務操作未執行 | 一致 |
預傳送訊息後,主動方應用沒有收到返回訊息儲存結果 | (2)訊息已進儲存(待確認),業務操作未執行 | 不一致 |
收到訊息儲存成功的返回結果,但未執行業務操作就失敗 | 訊息已進儲存(待確認),業務操作未執行 | 不一致 |
- 從訊息中介軟體的角度來分析
異常狀況 | 可能的狀態 | 一致性 |
---|---|---|
訊息中介軟體沒有收到主動方應用的業務操作處理結果 | (1)訊息已進儲存(待確認),業務操作未執行(或業務操作出錯回滾了) | 不一致 |
訊息中介軟體沒有收到主動方應用的業務操作處理結果 | (2)訊息已進儲存(待確認),業務操作成功 | 不一致 |
訊息中介軟體收到業務操作結果(成功/失敗),但處理訊息儲存中的訊息狀態失敗 | (1)訊息已進儲存(待確認),業務操作未執行(或業務操作出錯回滾了) | 不一致 |
訊息中介軟體收到業務操作結果(成功/失敗),但處理訊息儲存中的訊息狀態失敗 | (2)訊息已進儲存(待確認),業務操作成功 | 不一致 |
- 總結
異常狀況 | 一致性 | 異常處理方法 |
---|---|---|
訊息未進儲存,業務操作未執行 | 一致 | 無需處理 |
訊息已進儲存(狀態待確認),業務操作未執行 | 不一致 | 確認業務操作結果,處理訊息(刪除訊息) |
訊息已進儲存(狀態待確認),業務操作成功,但未通知傳送 | 不一致 | 確認業務操作結果,處理訊息(更新訊息狀態,執行訊息投遞) |
2.2 訊息消費一致性
- 訊息消費流程
2.2.1 訊息消費流程的異常點
- 訊息的消費確認流程中,任何一個環節都可能會出問題!
2.2.2 訊息消費流程異常處理
2.3 常規MQ處理流程
- Producer生成訊息併傳送給MQ(同步、非同步);
- MQ接收訊息並將訊息資料持久化到訊息儲存(持久化操作為可選配置);
- MQ向Producer返回訊息的接收結果(返回值、異常);
- Consumer監聽並消費MQ中的訊息;
- Consumer獲取到訊息後執行業務處理;
Consumer對已成功消費的訊息向MQ進行ACK確認(確認後的訊息將從MQ中刪除)。
佇列訊息模型的特點:
- 訊息生產者將訊息傳送到Queue中,然後訊息消費者監聽Queue並接收訊息;
- 訊息被確認消費以後,就會從Queue中刪除,所以訊息消費者不會消費到已經被消費的訊息;
- Queue支援存在多個消費者,但是對某一個訊息而言,只會有一個消費者成功消費。
常規MQ佇列訊息的處理流程無法實現訊息傳送一致性;
- 投遞訊息的流程其實就是訊息的消費流程,可細化。
- 解決方案如下
常規MQ佇列訊息的處理流程無法實現訊息傳送一致性,因此直接使用現成的MQ中介軟體產品無法實現可靠訊息最終一致性的分散式事務解決方案。
2.3 訊息冪等性
2.3.2 訊息重複傳送的原因
- 被動方應用接收到訊息,業務處理完成後應用出問題,訊息中介軟體不知道訊息處理結果,會重新投遞訊息。
- 被動方應用接收到訊息,業務處理完成後網路出問題,訊息中介軟體收不到訊息處理結果,會重新投遞訊息。
- 被動方應用接收到訊息,業務處理時間過長,訊息中介軟體因訊息超時未確認,會再次投遞訊息。
- 被動方應用接收到訊息,業務處理完成,訊息中介軟體問題導致收不到訊息處理結果,訊息會重新投遞。
- 被動方應用接收到訊息,業務處理完成,訊息中介軟體收到了訊息處理結果,但由於訊息儲存故障導致訊息沒能成功確認,訊息會再次投遞。
2.3.3 業務介面的冪等性設計
約束:被動方應用對於訊息的業務處理要實現冪等
- 對於存在同一請求資料會發生重複呼叫的業務介面,介面的業務邏輯要實現冪等性設計。
- 在實際的業務應用場景中,業務介面的冪等性設計,常結合可查詢操作一起使用。
- 支付訂單建立:商戶編號 + 商戶訂單號 + 訂單狀態
- 訂單更新處理:平臺訂單號 + 訂單狀態
- 會計系統記賬:系統來源 + 請求號
2.4 方案一:本地訊息服務的設計
2.4.1 面臨問題
- 現成MQ中介軟體不支援訊息傳送的一致性
- 直接改造MQ中介軟體難度很大
- 有什麼變通的實現方式?
2.4.2 主要流程
- 訊息儲存與業務儲存在同一個本地事務中進行,訊息儲存後設定為待確認狀態,並非同步將訊息傳送(注意需要非同步傳送訊息,不要影響主流程).
- 通過一定策略不斷將待確認的訊息重新傳送.
- 業務方回收到訊息,成功處理業務,並持久化完成後調主動方介面,通知主動方此訊息已經處理完成,主動方將資料庫中訊息狀態改為已傳送.
- 實現一個訊息管理系統,手動處理多次重發失敗已死亡的訊息.
2.4.3 優勢
- 訊息實時性較高
- 從應用設計開發的角度實現了訊息資料的可靠性,訊息資料的可靠性不依賴於MQ中介軟體,弱化了對MQ中介軟體的依賴
- 方案輕量容易實現
2.4.4 劣勢
- 業務繫結,耦合性強,不通用
- 訊息資料與業務資料同庫,佔用業務系統資源
- 業務系統在使用關係型資料庫的情況下,訊息服務效能會受到關係型資料庫併發效能的侷限
2.5 方案二:獨立訊息服務
2.5.1 面臨問題
- 現成MQ中介軟體不支援訊息傳送的一致性
- 直接改造MQ中介軟體難度很大
- 有什麼變通的實現方式?
2.5.2 主要流程
- 儲存預傳送訊息(主動方業務執行之前進行,預傳送的訊息儲存後狀態為待確認)
- 確認併傳送訊息(主動方業務完成之後,主動方或訊息狀態確認系統通過此介面將訊息變為取消或傳送中)
- 查詢狀態確認超時的訊息(訊息狀態確認系統使用)
- 確認訊息已被成功消費(被動方業務執行完成之後呼叫)
- 查詢消費確認超時的資訊
2.5.3 優勢
- 訊息服務獨立部署,獨立維護,獨立伸縮
- 訊息儲存可以按需選擇不同的資料庫來整合實現
- 訊息服務可以被相同的使用場景共用,降低訊息重複建設訊息服務的成本
- 從應用設計開發的角度實現了訊息資料的可靠性,訊息資料的可靠性不依賴於MQ中介軟體,弱化了MQ中介軟體特性的依賴
- 降低了業務系統與系統間的耦合,有利於系統的擴充套件維護
2.5.4 劣勢
- 一次訊息需要傳送兩次請求
- 主動方應用系統需要實現業務操作狀態校驗查詢介面
相關文章
- 分散式事務解決方案(三)【基於可靠訊息的最終一致性(獨立訊息服務實現)】分散式
- 分散式事務解決方案-RocketMQ實現可靠訊息最終一致性分散式MQ
- 分散式事務(5)---最終一致性方案之可靠訊息分散式
- 基於可靠訊息方案的分散式事務(二):Java中的事務分散式Java
- 分散式事務(六)之可靠訊息最終一致性分散式
- 分散式事務(八)Spring Cloud微服務系統基於Rocketmq可靠訊息最終一致性實現分散式事務分散式SpringCloud微服務MQ
- 基於可靠訊息方案的分散式事務:Lottor介紹分散式
- 分散式事務:基於可靠訊息服務分散式
- 基於可靠訊息方案的分散式事務(四):接入Lottor服務分散式
- 曹工雜談:分散式事務解決方案之基於本地訊息表實現最終一致性分散式
- 分散式事務方案 - 最終一致性分散式
- 基於RocketMq的分散式事務解決方案MQ分散式
- 分散式事務:訊息可靠傳送分散式
- 分散式事務(2)---強一致性分散式事務解決方案分散式
- 分散式事務(4)---最終一致性方案之TCC分散式
- 分散式事務解決方案--GTS(二)分散式
- 分散式訊息佇列RocketMQ--事務訊息--解決分散式事務的最佳實踐分散式佇列MQ
- 搞懂分散式技術19:使用RocketMQ事務訊息解決分散式事務分散式MQ
- 分散式事務解決方案分散式
- 分散式事務,強一致性方案有哪些?|分散式事務系列(二)分散式
- 分散式事務最終一致性的簡單案例分散式
- 常用的分散式事務解決方案分散式
- SpringCloud 分散式事務解決方案SpringGCCloud分散式
- 分散式事務之最終一致性實現方案分散式
- 一種基於柔性事務的分散式事務解決方案設計探究分散式
- RocketMQ訊息丟失解決方案:事務訊息MQ
- RocketMQ 分散式事務訊息MQ分散式
- 分散式事務解決方案彙總分散式
- MSSQL server分散式事務解決方案SQLServer分散式
- 分散式事務解決方案--GTS(一)分散式
- 分散式事務最終一致性-CAP框架輕鬆搞定分散式框架
- 遊戲陪玩app原始碼的可靠訊息最終一致性方案的實現遊戲APP原始碼
- 分散式事務解決方案(五)【TCC型方案】分散式
- RocketMQ系列(七)事務訊息(資料庫|最終一致性)MQ資料庫
- 關於分散式事務帶來的問題及解決方案分散式
- 分散式事務解決方案(一)【介紹】分散式
- 分散式事務利器——RocketMQ事務訊息的啟示分散式MQ
- .NetCore中使用分散式事務DTM的二階段訊息NetCore分散式