Rabbit MQ 怎么保證可靠性、冪等性、消費順序?


RabbitMQ如何保證消息的可靠性

RabbitMQ消息丟失的三種情況

生產者弄丟消息時的解決方法

  • 方法一:生產者在發送數據之前開啟RabbitMQ的事務(采用該種方法由於事務機制,會導致吞吐量下降,太消耗性能。)
  • 方法二:開啟confirm模式(使用springboot時在application.yml配置文件中做如下配置,實現confirm回調接口,生產者發送消息時設置confirm回調)
  • 小結: 事務機制和 confirm機制最大的不同在於,事務機制是同步的,你提交一個事務之后會阻塞在那兒,但是 confirm機制是異步的,你發送個消息之后就可以發送下一個消息,RabbitMQ 接收了之后會異步回調confirm接口通知你這個消息接收到了。一般在生產者這塊避免數據丟失,建議使用用 confirm 機制。

MQ自身弄丟消息時的解決方法

  • 第一步: 創建queue時設置為持久化隊列,這樣可以保證RabbitMQ持久化queue的元數據,此時還是不會持久化queue里的數據。
  • 第二步: 發送消息時將消息的deliveryMode設置為持久化,此時queue中的消息才會持久化到磁盤。
  • 總結:同時設置queue和message持久化以后,RabbitMQ 掛了再次重啟,也會從磁盤上重啟恢復 queue,恢復這個 queue 里的數據,保證數據不會丟失。
  • 但是:但是就算開啟持久化機制,也有可能出現上面說的的消息落盤時服務掛掉的情況。這時可以考慮結合生產者的confirm機制來處理,持久化機制開啟后消息只有成功落盤時才會通過confirm回調通知生產者,所以可以考慮生產者在生產消息時維護一個正在等待消息發送確認的隊列,如果超過一定時間還沒從confirm中收到對應消息的反饋,自動進行重發處理。

消費者自身弄丟消息時的解決方法

  • 方法:關閉自動ACK,使用手動ACK。RabbitMQ中有一個ACK機制,默認情況下消費者接收到到消息,RabbitMQ會自動提交ACK,之后這條消息就不會再發送給消費者了。我們可以更改為手動ACK模式,每次處理完消息之后,再手動ack一下。不過這樣可能會出現剛處理完還沒手動ack確認,消費者掛了,導致消息重復消費,不過我們只需要保證冪等性就好了,重復消費也不會造成問題。
  • 步驟一:在springboot中修改application.yml配置文件更改為手動ack模式
  • 步驟二:手動實現ack的callback

RabbitMQ保證消息可靠性總結

RabbitMQ保證消息可靠性總結

RabbitMQ如何保證消息的冪等性

如何保證消息隊列消費的冪等性,這一塊應該還是要結合業務來選擇合適的方法,有以下幾個方案:

  • 消費數據為了單純的寫入數據庫,可以先根據主鍵查詢數據是否已經存在,如果已經存在了就沒必要插入了。或者直接插入也沒問題,因為可以利用主鍵的唯一性來保證數據不會重復插入,重復插入只會報錯,但不會出現臟數據。
  • 消費數據只是為了緩存到redis當中,這種情況就是直接往redis中set value了,天然的冪等性。
  • 針對復雜的業務情況,可以在生產消息的時候給每個消息加一個全局唯一ID,消費者消費消息時根據這個ID去redis當中查詢之前是否消費過。如果沒有消費過,就進行消費並將這個消息的ID寫入到redis當中。如果已經消費過了,就無需再次消費了。

RabbitMQ如何保證消息的順序性

出現消費順序錯亂的情況

  • 為了提高處理效率,一個queue存在多個consumer
  • 一個queue只存在一個consumer,但是為了提高處理效率,consumer中使用了多線程進行處理

保證消息順序性的方法

  • 將原來的一個queue拆分成多個queue,每個queue都有一個自己的consumer。該種方案的核心是生產者在投遞消息的時候根據業務數據關鍵值(例如訂單ID哈希值對訂單隊列數取模)來將需要保證先后順序的同一類數據(同一個訂單的數據) 發送到同一個queue當中。
  • 一個queue就一個consumer,在consumer中維護多個內存隊列,根據業務數據關鍵值(例如訂單ID哈希值對內存隊列數取模)將消息加入到不同的內存隊列中,然后多個真正負責處理消息的線程去各自對應的內存隊列當中獲取消息進行消費。

RabbitMQ保證消息順序性總結:

核心思路就是根據業務數據關鍵值划分成多個消息集合,而且每個消息集合中的消息數據都是有序的,每個消息集合有自己獨立的一個consumer。多個消息集合的存在保證了消息消費的效率,每個有序的消息集合對應單個的consumer也保證了消息消費時的有序性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM