寫在前面:作供應鏈業務一年有餘了,這一年裏MQ幫咱們解決了不少問題,在此作一些經驗總結;另外,各個公司消息中間件提供的功能大同小異,最基礎的推消息、下游異常重試機制應該是都具有的,本文所述也是創建在這樣的能力基礎上的~
場景一:削峯填谷,下降響應時間,下游異常自動重試、保證成功redis
舉例:對庫存模塊而言,入庫是一個增量操做,當經過了數據校驗以後就理應執行成功,但入庫操做經常伴有複雜的寫庫邏輯及樂觀鎖衝突,同步模型平均響應時間長,且併發條件下樂觀鎖衝突失敗機率較大;這裏就能夠引入MQ,將寫庫操做異步處理,簡要流程以下:segmentfault
須要注意的是:
一、若是有重複發消息地可能性,MQ下游須要作業務冪等,整條鏈路要有併發鎖保護(redis實現併發悲觀鎖可參看文章:https://segmentfault.com/a/11...);
二、若是下游觸發異常,中間件通常會自動重試(併發樂觀鎖衝突自動重試可解決,中間件通常會提供一直重試、從新入隊、丟棄消息等模式,需根據具體場景選取,在此再也不贅述);若是是非重試可以解決的異常,則須要再監控到異常後,人工介入跳過、修復、補償;
三、示例狀況是上游無寫庫,若是上游有寫庫,可能出現發消息與事務寫庫兩個事件狀態不一致的狀況,通常會有三種狀況:併發
(1)先事務寫庫,再發消息;當發消息失敗時,寫庫事務已提交,沒法回滾; (2)先發消息,再事務寫庫;當寫庫失敗時,消息已發送,沒法回滾; (3)寫庫事務中發消息,若是發消息失敗,事務能夠回滾,但若是發消息成功後,事務提交時失敗(有這種可能),消息也沒法回滾;
若是上游沒法避免寫庫時,咱們通常採用先事務寫庫,再發送消息,由於消息中間件做爲基礎服務,通常是可靠的,很小几率出現發消息失敗;若是出現了,有兩種處理方式:異步
(1)發消息失敗,返回客戶端失敗,則須要腳本補償,回滾上游寫庫; (2)發消息失敗,只報警,但返回客戶端正常,則須要補償消息;
場景二:異步處理,服務解耦
舉例:每一次操做庫存後都須要記錄業務操做日誌,每一個Stock(庫存服務)接口都須要在完成庫存邏輯後,再調用Log(日誌服務)記錄操做日誌;若是採用同步調用模型,Stock服務就與Log服務耦合,依賴於Log服務的實時響應結果,若是Log服務掛了,Stock服務也就掛了,這不是咱們指望看到的;這裏就能夠引入MQ實現核心流程與非核心流程的解耦,簡要流程以下:spa
這樣,上游只需依賴MQ,通常而言,相比下游服務,中間件是更可靠的;經過MQ的能力,若是下游出現問題,主流程不會阻塞,有更多的時間修復,且更易補償;日誌
場景三:多下游的發佈訂閱
舉例:商品信息做爲供應鏈基礎數據,在幾乎全部系統都有應用;若是商品信息變動,其餘系統就須要接收變動信息,如何通知就是一個問題;同步通知模型會耦合全部下游服務,響應時間長,在增長或減小接收方時,上游代碼還須要變動,顯然不可行;這裏能夠採用多個consumer group訂閱同一個topic消息方式,異步接收變動事件,在增長或減小接收方時,下游服務consumer group主動訂閱或取消訂閱商品信息變動topic便可,簡要流程以下:code