rabbitmq(四)、消息丟失問題


 

丟失消息的三種情況:生產者弄丟了數據、RabbitMQ 弄丟了數據、消費端弄丟了數據。

一、生產者弄丟了數據

生產者將數據發送到 RabbitMQ 的時候,可能數據就在半路給搞丟了,因為網絡問題啥的,都有可能。

方法一:

  此時可以選擇用 RabbitMQ 提供的事務功能,就是生產者發送數據之前開啟 RabbitMQ 事務channel.txSelect,然后發送消息,如果消息沒有成功被 RabbitMQ 接收到,那么生產者會收到異常報錯,此時就可以回滾事務channel.txRollback,然后重試發送消息;如果收到了消息,那么可以提交事務channel.txCommit。

  但是,RabbitMQ 事務機制(同步)一搞,基本上吞吐量會下來,因為太耗性能。

方法二:

  可以開啟 confirm 模式,在生產者那里設置開啟 confirm 模式之后,你每次寫的消息都會分配一個唯一的 id,然后如果寫入了 RabbitMQ 中,RabbitMQ 會給你回傳一個 ack 消息,告訴你說這個消息 ok 了。如果 RabbitMQ 沒能處理這個消息,會回調你的一個 nack 接口,告訴你這個消息接收失敗,你可以重試。而且你可以結合這個機制自己在內存里維護每個消息 id 的狀態,如果超過一定時間還沒接收到這個消息的回調,那么你可以重發。

  事務機制和 cnofirm 機制最大的不同在於,事務機制是同步的,你提交一個事務之后會阻塞在那兒,但是 confirm 機制是異步的,你發送個消息之后就可以發送下一個消息,然后那個消息 RabbitMQ 接收了之后會異步回調你的一個接口通知你這個消息接收到了。

  所以一般在生產者這塊避免數據丟失,都是用 confirm 機制的。
二、RabbitMQ 弄丟了數據

 

  就是 RabbitMQ 自己弄丟了數據,這個你必須開啟 RabbitMQ 的持久化,就是消息寫入之后會持久化到磁盤,哪怕是 RabbitMQ 自己掛了,恢復之后會自動讀取之前存儲的數據,一般數據不會丟。除非極其罕見的是,RabbitMQ 還沒持久化,自己就掛了,可能導致少量數據丟失,但是這個概率較小。

設置持久化有兩個步驟:

1、創建 queue 的時候將其設置為持久化:這樣就可以保證 RabbitMQ 持久化 queue 的元數據,但是它是不會持久化 queue 里的數據的。

2、第二個是發送消息的時候將消息的 deliveryMode 設置為 2:就是將消息設置為持久化的,此時 RabbitMQ 就會將消息持久化到磁盤上去。

  必須要同時設置這兩個持久化才行,RabbitMQ 哪怕是掛了,再次重啟,也會從磁盤上重啟恢復 queue,恢復這個 queue 里的數據。

  注意,哪怕是你給 RabbitMQ 開啟了持久化機制,也有一種可能,就是這個消息寫到了 RabbitMQ 中,但是還沒來得及持久化到磁盤上,結果不巧,此時 RabbitMQ 掛了,就會導致內存里的一點點數據丟失。

  所以,持久化可以跟生產者那邊的 confirm 機制配合起來,只有消息被持久化到磁盤之后,才會通知生產者 ack 了,所以哪怕是在持久化到磁盤之前,RabbitMQ 掛了,數據丟了,生產者收不到 ack,你也是可以自己重發的。

三、消費端弄丟了數據

 

  RabbitMQ 如果丟失了數據,主要是因為你消費的時候,剛消費到,還沒處理,結果進程掛了,比如重啟了,那么就尷尬了,RabbitMQ 認為你都消費了,這數據就丟了。

 

  這個時候得用 RabbitMQ 提供的 ack 機制,簡單來說,就是你必須關閉 RabbitMQ 的自動 ack,可以通過一個 api 來調用就行,然后每次你自己代碼里確保處理完的時候,再在程序里 ack 一把。這樣的話,如果你還沒處理完,不就沒有 ack 了?那 RabbitMQ 就認為你還沒處理完,這個時候 RabbitMQ 會把這個消費分配給別的 consumer 去處理,消息是不會丟的。

 


免責聲明!

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



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