一般的消息中間件(MQ)只能保證消息不丟,但是不能保證重復發送等問題。
比如在使用Rabbitmq過程中,如何保證消息都能正確的投遞被消費,這個是要考慮的問題。
那么可靠性投遞所面臨的問題有哪些?
1. 如果發送的消息重復怎么辦。
2. 如果消息發送過程中丟了怎么辦。
3. 如何保證MQ節點成功收到消息。
針對這個問題RabbitMQ提供了以下幾個機制來解決:
- 生產者確認
- 持久化
- 手動Ack
下圖是Rabbitmq一個完整的消息可靠投遞的一個方案。
我們來分析下。
Step1:Producer所發送的數據是我們的業務數據,比如訂單信息。Producer在發送消息之前給我們的訂單信息寫入我們的本地數據庫(BIZ DB)中,BIZ DB是我們的業務數據庫,接着將要發送到消息存儲到消息記錄數據庫中(MSG DB),這個MSG DB就是存儲所有發送給Rabbitmq的消息記錄用的,寫入消息記錄表中該記錄字段status(狀態)會有幾個值,比如0表示消息發送中,1表示發送成功,2表示消息發送失敗,。
Step2:應用程序要消息發送給Rabbitmq的Broker,這個發送的消息屬於confirm模式,發送后需要Rabbitmq確認。
Step3:Rabbitmq Broker收到消息后會給Producer一個應答來確認信息,說我已經收到消息了。
Step4:緊跟上一步,Producer一直在監聽(Listener)Broker所確認的信息,在收到消息之后,根據收到消息的結果再去更新MSG DB中的消息發送狀態,將記錄status字段更新為1。
Step 5:但是在消息確認這個過程中可能由於網絡閃斷、MQ Broker端異常等原因導致 回送消息失敗或者異常。這個時候就需要發送方(生產者)對消息進行可靠性投遞了,保障消息不丟失,100%的投遞成功!(有一種極限情況是閃斷,Broker返回的成功確認消息,但是生產端由於網絡閃斷沒收到,這個時候重新投遞可能會造成消息重復,需要消費端去做冪等處理)所以我們需要有一個定時任務,(比如每5分鍾拉取一下處於中間狀態的消息,當然這個消息可以設置一個超時時間,比如超過1分鍾 Status = 0 ,也就說明了1分鍾這個時間窗口內,我們的消息沒有被確認,那么會被定時任務拉取出來)。
-
Step 5:但是在消息確認這個過程中可能由於網絡閃斷、MQ Broker端異常等原因導致 回送消息失敗或者異常。這個時候就需要發送方(生產者)對消息進行可靠性投遞了,保障消息不丟失,100%的投遞成功!(有一種極限情況是閃斷,Broker返回的成功確認消息,但是生產端由於網絡閃斷沒收到,這個時候重新投遞可能會造成消息重復,需要消費端去做冪等處理)所以我們需要有一個定時任務,(比如每5分鍾拉取一下處於中間狀態的消息,當然這個消息可以設置一個超時時間,比如超過1分鍾 Status = 0 ,也就說明了1分鍾這個時間窗口內,我們的消息沒有被確認,那么會被定時任務拉取出來)
-
Step 6:接下來我們把中間狀態的消息進行重新投遞 retry send,繼續發送消息到MQ ,當然也可能有多種原因導致發送失敗
-
Step 7:我們可以采用設置最大努力嘗試次數,比如投遞了3次,還是失敗,那么我們可以將最終狀態設置為Status = 2 ,最后 交由人工解決處理此類問題(或者把消息轉儲到失敗表中)。
作者:阿神
鏈接:https://www.imooc.com/article/49814
來源:慕課網
本文原創發布於慕課網 ,轉載請注明出處,謝謝合作
Step 6:接下來我們把中間狀態的消息進行重新投遞 retry send,繼續發送消息到MQ ,當然也可能有多種原因導致發送失敗。