rabbitmq(四)、消息丢失问题
?
丟失消息的三種情況:生產(chǎn)者弄丟了數(shù)據(jù)、RabbitMQ 弄丟了數(shù)據(jù)、消費端弄丟了數(shù)據(jù)。
一、生產(chǎn)者弄丟了數(shù)據(jù)
生產(chǎn)者將數(shù)據(jù)發(fā)送到 RabbitMQ 的時候,可能數(shù)據(jù)就在半路給搞丟了,因為網(wǎng)絡(luò)問題啥的,都有可能。
方法一:
此時可以選擇用 RabbitMQ 提供的事務(wù)功能,就是生產(chǎn)者發(fā)送數(shù)據(jù)之前開啟 RabbitMQ 事務(wù)channel.txSelect,然后發(fā)送消息,如果消息沒有成功被 RabbitMQ 接收到,那么生產(chǎn)者會收到異常報錯,此時就可以回滾事務(wù)channel.txRollback,然后重試發(fā)送消息;如果收到了消息,那么可以提交事務(wù)channel.txCommit。
但是,RabbitMQ 事務(wù)機制(同步)一搞,基本上吞吐量會下來,因為太耗性能。
方法二:
可以開啟 confirm 模式,在生產(chǎn)者那里設(shè)置開啟 confirm 模式之后,你每次寫的消息都會分配一個唯一的 id,然后如果寫入了 RabbitMQ 中,RabbitMQ 會給你回傳一個 ack 消息,告訴你說這個消息 ok 了。如果 RabbitMQ 沒能處理這個消息,會回調(diào)你的一個 nack 接口,告訴你這個消息接收失敗,你可以重試。而且你可以結(jié)合這個機制自己在內(nèi)存里維護每個消息 id 的狀態(tài),如果超過一定時間還沒接收到這個消息的回調(diào),那么你可以重發(fā)。
事務(wù)機制和 cnofirm 機制最大的不同在于,事務(wù)機制是同步的,你提交一個事務(wù)之后會阻塞在那兒,但是 confirm 機制是異步的,你發(fā)送個消息之后就可以發(fā)送下一個消息,然后那個消息 RabbitMQ 接收了之后會異步回調(diào)你的一個接口通知你這個消息接收到了。
所以一般在生產(chǎn)者這塊避免數(shù)據(jù)丟失,都是用 confirm 機制的。
二、RabbitMQ 弄丟了數(shù)據(jù)
?
就是 RabbitMQ 自己弄丟了數(shù)據(jù),這個你必須開啟 RabbitMQ 的持久化,就是消息寫入之后會持久化到磁盤,哪怕是 RabbitMQ 自己掛了,恢復(fù)之后會自動讀取之前存儲的數(shù)據(jù),一般數(shù)據(jù)不會丟。除非極其罕見的是,RabbitMQ 還沒持久化,自己就掛了,可能導(dǎo)致少量數(shù)據(jù)丟失,但是這個概率較小。
設(shè)置持久化有兩個步驟:
1、創(chuàng)建 queue 的時候?qū)⑵湓O(shè)置為持久化:這樣就可以保證 RabbitMQ 持久化 queue 的元數(shù)據(jù),但是它是不會持久化 queue 里的數(shù)據(jù)的。
2、第二個是發(fā)送消息的時候?qū)⑾⒌?deliveryMode 設(shè)置為 2:就是將消息設(shè)置為持久化的,此時 RabbitMQ 就會將消息持久化到磁盤上去。
必須要同時設(shè)置這兩個持久化才行,RabbitMQ 哪怕是掛了,再次重啟,也會從磁盤上重啟恢復(fù) queue,恢復(fù)這個 queue 里的數(shù)據(jù)。
注意,哪怕是你給 RabbitMQ 開啟了持久化機制,也有一種可能,就是這個消息寫到了 RabbitMQ 中,但是還沒來得及持久化到磁盤上,結(jié)果不巧,此時 RabbitMQ 掛了,就會導(dǎo)致內(nèi)存里的一點點數(shù)據(jù)丟失。
所以,持久化可以跟生產(chǎn)者那邊的 confirm 機制配合起來,只有消息被持久化到磁盤之后,才會通知生產(chǎn)者 ack 了,所以哪怕是在持久化到磁盤之前,RabbitMQ 掛了,數(shù)據(jù)丟了,生產(chǎn)者收不到 ack,你也是可以自己重發(fā)的。
三、消費端弄丟了數(shù)據(jù)
?
RabbitMQ 如果丟失了數(shù)據(jù),主要是因為你消費的時候,剛消費到,還沒處理,結(jié)果進程掛了,比如重啟了,那么就尷尬了,RabbitMQ 認(rèn)為你都消費了,這數(shù)據(jù)就丟了。
?
這個時候得用 RabbitMQ 提供的 ack 機制,簡單來說,就是你必須關(guān)閉 RabbitMQ 的自動 ack,可以通過一個 api 來調(diào)用就行,然后每次你自己代碼里確保處理完的時候,再在程序里 ack 一把。這樣的話,如果你還沒處理完,不就沒有 ack 了?那 RabbitMQ 就認(rèn)為你還沒處理完,這個時候 RabbitMQ 會把這個消費分配給別的 consumer 去處理,消息是不會丟的。
?
轉(zhuǎn)載于:https://www.cnblogs.com/dwxblogs/p/10951314.html
總結(jié)
以上是生活随笔為你收集整理的rabbitmq(四)、消息丢失问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CTS/APIO后文化课游记
- 下一篇: Oracle基于布尔的盲注总结