RabbitMQ系列(四)--消息如何保證可靠性傳輸以及冪等性

1、消息如何保證可靠性傳輸

1.一、可能出現消息丟失的狀況

  一、Producer在把Message發送Broker的過程當中,由於網絡問題等發生丟失,或者Message到了Broker,可是出了問題,沒有保存下來算法

  針對這個問題,Producer能夠開啓MQ的事務,若是這個過程出現異常,進行回滾,可是有個很大的問題,你提交一個事務就會阻塞在那,數據庫

很是影響性能,生產環境確定不會開啓事務,通常都是使用confirm機制緩存

  二、Broker接收到Message暫存到內存,Consumer還沒來得及消費,Broker掛掉了網絡

  能夠經過持久化設置去解決:併發

    1).建立Queue的時候設置持久化,保證Broker持久化Queue的元數據,可是不會持久化Queue裏面的消息運維

    2).將Message的deliveryMode設置爲2,能夠將消息持久化到磁盤,這樣只有Message支持化到磁盤以後纔會發送通知Producer ack分佈式

  這兩步事後,即便Broker掛了,Producer確定收不到ack的,就能夠進行重發高併發

  三、Consumer有消費到Message,可是內部出現問題,Message還沒處理,Broker覺得Consumer處理完了,只會把後續的消息發送性能

  這時候,就要關閉autoack,消息處理事後,進行手動ackspa

1.二、通常經過生產端保證可靠性投遞

  一、保證消息的成功發出

  二、保證MQ節點的成功接收

  三、發送端收到MQ節點(Broker)的確認應答

  四、完善的消息補償機制

1.三、解決方案

一、消息落庫,對消息狀態進行變動,對於高併發環境下數據庫壓力很大,由於須要寫屢次數據庫

 

總體流程:

  一、業務數據和消息都進行落庫

  二、生產端發送message給Broker

  三、Broker給Confirm響應返回生產端

  四、接收到confirm,對message狀態更改

  五、分佈式定時任務獲取消息的狀態

  六、若是消息不能成功投遞,從新進行發送,記錄重發次數

  七、當重發3次以後,將狀態修改,只能人工進行干預

 

二、消息的延遲投遞,作二次確認,回調檢查。適合高併發環境,減小寫庫的次數

 

 總體流程:

  一、上游服務首先將業務代碼入庫,發送message給Broker

  二、發送第二個延遲確認消息

  三、下游服務監聽消息進行消費

  四、發送確認消息,這裏不是confirm機制,而是一條新的消息

  五、經過回調服務監聽這個confirm消息,而後把消息進行入庫

  六、回調服務檢查到延遲確認消息,會在數據庫查詢是否有這條消息

  七、若是沒有查到這條消息,回調服務經過RPC給一個從新發送命令到上游系統

 

相比第一種方案,這裏減小了一次message入庫,confirm機制是消息可靠性投遞的一個核心,在下篇文章會講到

2、如何保證消息的冪等性

  首先,不管是RabbitMQ、RocketMQ仍是kafka,都有可能出現消息的重複發送,這個是MQ沒法保障的,而冪等性是開發或者運維人員須要保證的

  所謂消息的冪等性是指即便收到屢次消息,也不會重複消費,這點很重要,例如用戶付錢,點的太快了,付了屢次,可是你也只能扣一次錢,

否則要罵人了

2.一、RabbitMQ可能致使出現非冪等性的狀況

  一、可靠性消息投遞機制:consumer回覆confirm出現網絡閃斷,producer沒有收到ack,定時任務輪詢可能就會從新發送消息,這樣consumer就

會收到兩條消息

  二、MQ Broker與消費端傳輸消息的過程出現網絡抖動

  三、消費端故障或異常

2.二、kafka可能出現非冪等性的狀況

在Consumer端offset沒有提交的時候,Consumer重啓了,這時候就會出現重複消費的狀況

2.三、解決方案

一、惟一ID+指紋碼

  總體實現相對簡單,須要進行數據庫寫入,利用數據庫主鍵去重,使用ID進行分庫分表算法路由,從單庫的冪等性到多庫的冪等性

  1).這裏惟一ID通常就是業務表的主鍵,好比商品ID

  2).指紋碼:每次操做都要生成指紋碼,能夠用時間戳+業務編號+...組成,目的是保證每次操做都是正常的

總體流程:

  一、須要一個統一ID生成服務,爲了保證可靠性,上游服務也要有個本地ID生成服務,而後發送消息給Broker

  二、須要ID規則路由組件去監聽消息,先入庫,若是入庫成功,證實沒有重複,而後發給下游,若是發現庫裏面有了這條消息,就不發給下游

 

二、利用Redis的原子性實現

  Redis的實現性能比較好,並且Redis通常使用集羣,不用擔憂某臺機器掛掉了,影響服務。

存在的問題:

  是否要進行數據落庫,若是落庫的話,怎麼保證緩存和storage的一致性、事務,若是不落庫,如何設置定時同步策略

相關文章
相關標籤/搜索