1、保證消息不丟失(三步)
1.1、開啟事務(不推薦)
1.2、開啟confirm(推薦)
1.3、開啟RabbitMQ持久化(交換機、隊列、消息)
1.4、關閉RabbitMQ自動ack(改成手動)
2、保證消息不重復消費
2.1、冪等性(每個消息用一個唯一標識來區分,消費前先判斷標識有沒有被消費過,若已消費過,則直接ACK)
3、RabbitMQ如何保證消息的順序性
將消息放入同一個交換機,交給同一個隊列,這個隊列只有一個消費者,消費者只允許同時開啟一個線程
4、RabbitMQ消息重試機制
消費者在消費消息的時候,如果消費者業務邏輯出現程序異常,這時候應該如何處理?
答案:使用消息重試機制(SpringBoot默認3次消息重試機制)
如何合適選擇重試機制
消費者取到消息后,調用第三方接口,接口無法訪問,需要使用重試機制
消費者取到消息后,拋出數據轉換異常,不需要重試機制,需要發布者進行解決。
5、SpringBoot消息重試機制
@EnableRetry注解:表示啟用重試機制(value表示哪些異常需要觸發重試,maxAttempts設置最大重試次數,delay表示重試的延遲時間,multiplier表示上一次延時時間是這一次的倍數)
eg、@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 1.5))
@Recover注解:當重試次數達到設置的最大次數的時候,程序還是執行異常,調用的回調函數。
6、RabbitMQ死信隊列
死信隊列是當消息在一個隊列因為下列原因:
a、消息被拒絕(basic.reject或basic.nack)並且requeue=false.
b、消息TTL過期
c、隊列達到最大長度(隊列滿了,數據無法添加到mq中)
變成了 “死信隊列” 后被重新投遞(publish)到另一個Exchange,然后重新消費。說白了就是沒有被消費的消息換個地方重新被消費
7、RabbitMQ解決分布式事務
經典案例,以目前流行的外賣為例,用戶下單后,調用訂單服務,訂單服務調用派單系統通知送外賣人員送單,這時候訂單系統與派單系統采用MQ異步通訊。
RabbitMQ解決分布式事務原理
答案:采用最終一致性原理
需要保證以下三要素:
a、確保生產者一定要將數據投遞到MQ服務器中(采用MQ消息確認機制)
b、確保消費者能夠正確消費消息,采用手動ACK模式(注意重試、冪等性問題)
c、如何保證第一個事務先執行,采用補償機制,在創建一個補單消費者進行監聽,如果訂單沒有創建成功,進行補單。(如果第一個事務中出錯,補單消費者會在重新執行一次第一個事務,例如第一個事務是添加訂單表,如果失敗在補單的時候重新生成訂單記錄,由於訂單號唯一,所以不會重復)
8、RabbitMQ保證消息不丟失的具體方案
前提:
(1)開啟confirm
(2)開啟RabbitMQ的持久化(交換機、隊列、消息)
(3)關閉RabbitMQ的自動ack(改成手動)
(4)配置消費重試次數,消費重試間隔時間等
涉及到的技術點:
MQ、Redis、定時任務
8.1、保證投放消息不丟失
(1)先將消息放入生產者Redis(此時消息的狀態為未投放),再放入隊列
(2)根據confirm(ReturnCallback和ConfirmCallback)的結果來確定消息是否投遞成功,
投遞成功的,修改生產者redis中消息的投遞狀態為已投遞
投遞失敗的消息將會放入失敗的Redis,並從生產者Redis中刪除,由定時任務定期掃描並重新投遞
(3)生產者Redis定時任務
生產者Redis定時任務專門掃描生產者Redis中存放了一定時間,但是狀態還是未投放的消息
此消息會被認為已經投遞,但是沒有任何反饋結果(由於不可知因素,導致沒有ReturnCallback,也沒有ConfirmCallback),
此類消息被掃描到后,會放入失敗的Redis,並從生產者Redis中刪除,由定時任務定期掃描並重新投遞
(4)還需要一個專門的定時任務掃描生產者Redis中存放了很久,仍然未消費的數據(狀態為已投遞),此類消息被掃描到后,會放入失敗的Redis,並從生產者Redis中刪除,由定時任務定期掃描並重新投遞
(5)掃描失敗的Redis的定時任務都遵循一條原則,一條消息最多被重新投遞三次,若投遞了三次仍然失敗,則記錄日志,記錄到數據庫,不會再投遞,需要人工干預處理
8.2、保證消費消息不丟失
(1)消費者取到消息后,從消息中取出唯一標識,先判斷此消息有沒有被消費過,若已消費過,則直接ACK(避免重復消費)
(2)正常處理成功后,將生產者Redis中的此消息刪除,並ACK(告訴server端此消息已成功消費)
(3)遇到異常時,捕獲異常,驗證自己在消息中設定的重試次數是否超過閥值,若超過,則放入死信隊列,若未超過,則向將消息中的重試次數加1,拋出自定義異常,進入重試機制
(4)有專門的消費者用於處理死信隊列中消費多次仍未消費成功的數據,可以記錄日志,入庫,人工干預處理