【消息隊列】RabbitMQ如何處理消息丟失

首先明確一點 一條消息的傳送流程:生產者->MQ->消費者網絡

因此有三個地方都會丟失數據:異步

生產者發送給MQ的途中出現網絡問題
MQ本身沒保管好弄丟了
消費者拿到數據後出錯了沒有最終完成任務

依次分析性能

1)生產者弄丟了數據code

生產者將數據發送到rabbitmq的時候,可能由於網絡問題致使數據就在半路給搞丟了。接口

1.使用事務(性能差)
能夠選擇用rabbitmq提供的事務功能,在生產者發送數據以前開啓rabbitmq事務(channel.txSelect),而後發送消息,若是消息沒有成功被rabbitmq接收到,那麼生產者會收到異常報錯,此時就能夠回滾事務(channel.txRollback),而後重試發送消息;若是收到了消息,那麼能夠提交事務(channel.txCommit)。可是問題是,開始rabbitmq事務機制,基本上吞吐量會下來,由於太耗性能。rabbitmq

2.發送回執確認(推薦)
能夠開啓confirm模式,在生產者那裏設置開啓confirm模式以後,你每次寫的消息都會分配一個惟一的id,而後若是寫入了rabbitmq中,rabbitmq會給你回傳一個ack消息,告訴你說這個消息ok了。若是rabbitmq沒能處理這個消息,會回調你一個nack接口,告訴你這個消息接收失敗,你能夠重試。並且你能夠結合這個機制本身在內存裏維護每一個消息id的狀態,若是超過必定時間還沒接收到這個消息的回調,那麼你能夠重發。
  事務機制和cnofirm機制最大的不一樣在於,事務機制是同步的,你提交一個事務以後會阻塞在那兒,可是confirm機制是異步的,你發送個消息以後就能夠發送下一個消息,而後那個消息rabbitmq接收了以後會異步回調你一個接口通知你這個消息接收到了。進程

因此通常在生產者這塊避免數據丟失,都是用confirm機制的。事務

2)RabbitMQ弄丟了數據-開啓RabbitMQ的數據持久化內存

  爲了防止rabbitmq本身弄丟了數據,這個你必須開啓rabbitmq的持久化,就是消息寫入以後會持久化到磁盤,哪怕是rabbitmq本身掛了,恢復以後會自動讀取以前存儲的數據,通常數據不會丟。除非極其罕見的是,rabbitmq還沒持久化,本身就掛了,可能致使少許數據會丟失的,可是這個機率較小。同步

  設置持久化有兩個步驟,第一個是建立queue的時候將其設置爲持久化的,這樣就能夠保證rabbitmq持久化queue的元數據,可是不會持久化queue裏的數據;第二個是發送消息的時候將消息的deliveryMode設置爲2,就是將消息設置爲持久化的,此時rabbitmq就會將消息持久化到磁盤上去。必需要同時設置這兩個持久化才行,rabbitmq哪怕是掛了,再次重啓,也會從磁盤上重啓恢復queue,恢復這個queue裏的數據。

  並且持久化能夠跟生產者那邊的confirm機制配合起來,只有消息被持久化到磁盤以後,纔會通知生產者ack了,因此哪怕是在持久化到磁盤以前,rabbitmq掛了,數據丟了,生產者收不到ack,你也是能夠本身重發的。

  若生產者那邊的confirm機制未開啓的狀況下,哪怕是你給rabbitmq開啓了持久化機制,也有一種可能,就是這個消息寫到了rabbitmq中,可是還沒來得及持久化到磁盤上,結果不巧,此時rabbitmq掛了,就會致使內存裏的一點點數據會丟失。

3)消費端弄丟了數據

  主要是由於你消費的時候,剛消費到,還沒處理,結果進程掛了好比重啓了,那麼就尷尬了,RabbitMQ認爲你都消費了,這數據就丟了。或者消費者拿到數據以後掛了,這時候須要MQ從新指派另外一個消費者去執行任務(一塊肉,剛用筷子夾起來,發地震抖了一下,肉掉了)

  這個時候得用RabbitMQ提供的ack機制,也是一種處理完成發送回執確認的機制。若是MQ等待一段時間後你沒有發送過來處理完成 那麼RabbitMQ就認爲你還沒處理完,這個時候RabbitMQ會把這個消費分配給別的consumer去處理,消息是不會丟的。

相關文章
相關標籤/搜索