1. 程式人生 > >分散式事務實戰(二)--可靠訊息的最終一致性方案(訊息的一致性問題)

分散式事務實戰(二)--可靠訊息的最終一致性方案(訊息的一致性問題)

前言

訊息傳送一致性問題:
在分散式部署環境下,通過網路進行通訊,就會有資料傳世的不確定性,也就是CAP中的P【會出現分割槽容錯性的問題】。主動方傳送訊息到訊息中介軟體以及訊息中介軟體到被動方應用題都會出現網路的問題;

如何保證一致性問題

場景:比如說支付模組,訂單完成之後需要通知其他系統的場景。
解決方式1:先處理本地事務;再發送訊息
問題:如果本地事務操作成功,但是由於各種異常情況(本身應用故障|訊息系統故障|網路故障),訊息發不出去,就造成了訂單系統與其他三方系統的資料不一致的情況。

解決方式2:先發送訊息,再處理本地事務。
問題:這種情況,更糟糕了,訊息發出去了,但是本地事務操作失敗,也會造成了訂單系統與其他三方系統的資料不一致的情況。

解決方式3:
JMS標準中的XA協議是否可以保證傳送一致性呢?
JMS的標準API中是有支援XA協議的全域性性事務型介面。
問題:引入XA方式的分散式事務,要求所有操作的資源必須支援XA協議,兩階段提交協議本身的成本;持久化成本高,全域性鎖定,效能低。

解決方式4:
這裡寫圖片描述
1.主動方先把訊息傳送給訊息中介軟體,訊息狀態為待確認。
2.訊息中介軟體收到訊息後,只做儲存,不會投遞;
3.訊息中介軟體返回持久化結果(成功/失敗)。
如果失敗,則結束操作;如果成功,接著執行業務操作。
4.業務操作完成後,需要吧操作結果傳送給訊息中介軟體。
5.訊息中介軟體收到業務操作結果後,根據結果進行處理。 如果成功,則把訊息狀態改為“待發送”;後續進行投遞; 如果失敗,則刪除訊息,結束。
5.前面流程ok之後, 就會進行訊息投遞。

異常情況分析

從傳送方的角度來看

異常情況 場景分析(原因分析) 是否一致
預傳送失敗 訊息未持久化;業務操作為儲存;可能是因為(傳送方應用異常,網路,中介軟體,訊息儲存等異常) 一致
預傳送訊息成功:主動方未收到訊息儲存結果;訊息未持久化;業務未執行 訊息未持久化;業務未執行 一致
預傳送訊息成功:主動方未收到訊息儲存結果;訊息已持久化 ;業務未執行 訊息已持久化;業務未執行 不一致
收到訊息持久化成功的訊息:還沒來得及執行業務操作就異常,或者執行失敗了 訊息已持久化;業務未執行 不一致

從中介軟體的角度來看

異常情況 場景分析(原因分析) 是否一致
中介軟體未收到主動方的操作結果1 訊息已持久化;業務操作未執行(或者失敗回滾) 不一致
中介軟體未收到主動方的操作結果2 訊息已持久化;業務操作成功 不一致
訊息中介軟體收到操作結果,但持久化過程中失敗1 訊息持久化(待確認,狀態應該更新為廢棄);業務操作未執行(或者失敗回滾) 不一致
訊息中介軟體收到操作結果,但持久化過程中失敗2 訊息持久化(待確認,狀態應該更新為待發送);業務操作成功 不一致

總結髮送端的異常場景:

異常情況 是否一致 處理方案
訊息未持久化,業務操作未執行 一致 一致
訊息已持久化(狀態待確認),業務操作未執行 不一致 查詢確認業務操作結果,刪除訊息
訊息已持久化(狀態待確認),業務已經執行 不一致 查詢確認業務操作結果,更新為待發送狀態,執行投遞

MQ佇列訊息
模型的特點:
1.訊息生產者將訊息傳送到Queue中,消費者監聽queue,並接受訊息。
2.訊息被確認消費之後,會從queue中刪除;
3.queue支援多個消費者消費,但對某一個訊息,只會有一個消費者消費成功

生成與消費的流程:
1.生產者生成併發送給MQ(同步或者非同步)
2.MQ接收到訊息,持久化到訊息儲存(持久化是可選 )
3.MQ向producer返回訊息的接收結果
4.消費者會監聽並消費MQ的訊息
5.消費者獲取訊息後,執行業務,對消費成功的訊息向MQ傳送ACk確認
6.確認後,會從佇列中刪除。

結論:正常的MQ佇列的處理流程無法真正實現訊息傳送一致性;因為他進入佇列中沒有等到業務確認(或者生產者沒有收到訊息的確認收到的訊息)就進行投遞了。會存在一定的風險。

從消費者的角度來看

異常情況 場景分析(原因分析) 操作
1 消費端收到訊息,業務處理後應用(或者網路異常或者超時)異常,訊息中介軟體不知道處理結果 重新投遞
2 消費端收到訊息,業務處理完成,訊息中介軟體的問題導致收不到ACK應答 重新投遞
3 消費端收到訊息,業務處理完成,訊息中介軟體收到應答,但持久化異常 重新投遞

總體來說,消費過程中肯定會出現重複投遞的問題,基本上就是因為沒有及時確認ACK,所以消費端一定要在業務層面做好冪等的控制。但是訊息重發也是有次數限制,會有down機的風險的,所以會限制次數,人工介入干預;後期定期清理。

總結

基於以上的常規以及異常的流程,我們就可以設計一套一致性的系統。 但目前現有的MQ中介軟體不支援訊息傳送的一致性流程(先持久化再被業務確認後然後再發送); 如果直接改造原始碼,難度比較大,並且後續人員維護也非常繁瑣。

至於變通的方案,下一篇會講到 :分散式事務實戰(三)–可靠性訊息的最終一致性方案【基於本地訊息服務】