生產端的可靠性投遞數據庫
解決方案服務器
消息落庫架構圖網絡
上圖中BIZ DB爲咱們的業務庫,比方說保存訂單;MSG DB爲消息庫,保存咱們發送到MQ消息。若是在Step 3的時候,網絡出現故障,Confirm機制沒有收到broker的消息確認。咱們須要設置一個時間臨界點,好比說5分鐘,檢索出消息庫中狀態爲0的消息,經過分佈式定時任務,好比XXL-Job或者Elastic-Job。但有可能出現消息剛發出去,尚未Confirm成功,定時任務就已經啓動了,並把發送成功的消息確認爲未成功,因此咱們須要有一個Step 6,給入庫消息一個最大的容忍時間,好比說2分鐘到5分鐘。好比消息入庫的時候須要帶上時間,咱們取出狀態爲0的消息造成一個集合,而後過濾該集合的時間爲2分鐘以上的消息進行從新發送。因爲MQ消息的配置自己有問題的狀況下(好比說路由,隊列,交換機),會出現消息永遠沒法發送成功,這個時候咱們須要有一個消息重試的機制,好比3次,若是3次都沒有發送成功,則更新該消息狀態爲2,表示失敗。架構
可是這種方式有必定的侷限性,由於要作數據庫的二次入庫操做,磁盤io會成爲瓶頸,在高併發的場景下並不合適。因爲咱們的業務入庫是必須的,因此咱們要考慮消息入庫是否能夠取消。因此咱們要考慮第二種方式:消息的延遲投遞,作二次確認,回調檢查。併發
這裏的Upstream service爲咱們的上流業務,咱們確定要作的是進行業務入庫,而後再發消息到Broker,這裏的不一樣在於Step2,Step2須要再發一條消息,但這條消息是一個延遲消息(這種延遲消息並非死信隊列那種延遲消息,咱們能夠用DelayQueue來發這條消息),多是2到5分鐘以後才發出去的,該消息與Step1雖然消息內容同樣,可是它們投遞的隊列不一樣,該隊列被Call back service監聽。Downstream service爲MQ消費者,但它同時也是消息投遞者,它會在Step4發送一個confirm消息(該消息也是一個MQ消息)到Broker,可是這條消息並非發給上流生產者的,而是發給Call back service的,Call back service做爲消息消費者收到這條消息,而後作一個消息的持久化存儲,存入數據庫中。3到5分鐘以後,Call back service收到延遲發送的Step2的消息,再去對比消息數據庫中的消息,更新消息數據庫中的狀態爲1。若是在此過程當中,Downstream service沒有發送消息給Call back service,則消息數據庫中沒有這條消息,當Call back service收到Step2的延遲消息的時候,就經過RPC或者Restful從新調用upstream中的業務庫檢查後,再從新發送一條step1消息,走下一個流程。分佈式
以上的這個方案並不能保證100%的消息投遞,可是它對於第一種方案的好處是少進行了一次DB操做,保證高併發的性能。好比說第一種方式的吞吐量爲1000,那第二種方式的吞吐量就能夠翻倍到2000,能夠節省一臺服務器。這裏把消息補償機制從第一種方式的嵌入到核心鏈路給解耦爲一個單獨的微服務,核心鏈路則只有消息發送到消息處理。同時下游業務處理應該加上消息的冪等,確保只處理一個消息。微服務