微服務保持事物的一致性

解決方案一:

​ 使用中間表控制微服務之間的事物的一致性,即在A,B兩個微服務中,是一個遊戲買裝備的業務流程,A微服務負責扣除用戶的金幣,B微服務負責生成相應的訂單數據,在我們用戶夠買裝備時,當A服務扣除金幣成功時相應的B微服務有以下幾處理結果態:①成功②失敗③超時 當B微服務發生二或者是三中的一種時即事物不能保持一致性,此時我們可以採用中間表的機制實現微服務間事物的一致性。我們設計一箇中間表用來存放用戶夠買裝備的A,B兩個微服務的狀態,當我們A完成時狀態爲1B完成時狀態爲1,B失敗時狀態爲0,我們設置一個定時的輪循查詢該表數據,若A,B狀態不一致則進行相應的事物控制,則可以實現微服務之間的事物的一致性。

 

解決方案二:

MQ(非事務消息)

​ 通常情況下,在使用非事務消息支持的MQ產品時,我們很難將業務操作與對MQ的操作放在一個本地事務域中管理。通俗點描述,還是以上述提到的“跨行轉賬”爲例,我們很難保證在扣款完成之後對MQ投遞消息的操作就一定能成功。這樣一致性似乎很難保證。

先從消息生產者這端來分析,請看僞代碼:

根據上述代碼及註釋,我們來分析下可能的情況:

  1. 操作數據庫成功,向MQ中投遞消息也成功,皆大歡喜

  2. 操作數據庫失敗,不會向MQ中投遞消息了

  3. 操作數據庫成功,但是向MQ中投遞消息時失敗,向外拋出了異常,剛剛執行的更新數據庫的操作將被回滾

從上面分析的幾種情況來看,貌似問題都不大的。那麼我們來分析下消費者端面臨的問題:

  1. 消息出列後,消費者對應的業務操作要執行成功。如果業務執行失敗,消息不能失效或者丟失。需要保證消息與業務操作一致

  2. 儘量避免消息重複消費。如果重複消費,也不能因此影響業務結果

如何保證消息與業務操作一致,不丟失?

主流的MQ產品都具有持久化消息的功能。如果消費者宕機或者消費失敗,都可以執行重試機制的(有些MQ可以自定義重試次數)。

如何避免消息被重複消費造成的問題?

  1. 保證消費者調用業務的服務接口的冪等性

  2. 通過消費日誌或者類似狀態表來記錄消費狀態,便於判斷(建議在業務上自行實現,而不依賴MQ產品提供該特性)

總結:這種方式比較常見,性能和吞吐量是優於使用關係型數據庫消息表的方案。如果MQ自身和業務都具有高可用性,理論上是可以滿足大部分的業務場景的。不過在沒有充分測試的情況下,不建議在交易業務中直接使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章