消息隊列怎麼處理消息丟失問題

rabbitmq處理辦法

1,生產者丟失數據

生產者由於網絡問題,數據剛發出去就斷掉了

解決辦法:

1),開啓tabbitmq事務,如果消息沒有被rabbitmq接收到就回滾事務,繼續重試,否則就提交事務,但這種效率較慢

2),開啓confirm模式,這是每個消息都會被分配一個id,如果消息被rabbitmq成功接收,會返回ack消息,如果消息沒有被rabbitmq處理,會回調一個nack接口告訴你處理失敗,然後你可以重試。這種方式優點是異步的,發送完這個消息後可以繼續發送下一個消息;

2,rabbitmq丟失數據

爲了防止rabbitmq丟失數據,必須開通rabbitmq數據持久化,將數據寫入磁盤,這樣哪怕rabbitmq宕機了,重啓後也能讀取磁盤內的數據;

持久化方式:

1),第一個是創建queue的時候將其設置爲持久化的,這樣就可以保證rabbitmq持久化queue的元數據,但是不會持久化queue裏的數據

2),第二個是發送消息的時候將消息的deliveryMode設置爲2,就是將消息設置爲持久化的,此時rabbitmq就會將消息持久化到磁盤上去。必須要同時設置這兩個持久化才行,rabbitmq哪怕是掛了,再次重啓,也會從磁盤上重啓恢復queue,恢復這個queue裏的數據。

注意:持久化必須和confirm結合起來使用,數據必須被寫入磁盤後纔會返回給生產這ack,否則如果數據還沒持久化rabbitmq就掛了,還是會丟失消息;

3,消費者丟失數據

消費者剛剛接收消息,但還沒來得及處理就掛了,而rabbitmq認爲你已經消費了,那消息就丟失了

解決辦法:

1),調用rabbitmq提供的ack機制(開啓重試默認3次),並把ack調爲手動調用,就是消費者每次消費消息成功會去調用一個api接口,返回rabbitmq   一個ack消息,通知他消費完成,如果沒有返回ack,rabbitmq會認爲這個消息還沒被消費,會繼續分配給下個消費者消費;

 

kafuka處理辦法

1,生產者丟失數據

設置了ack=all,一定不會丟,要求是,你的leader接收到消息,所有的follower都同步到了消息之後,才認爲本次寫成功了。如果沒滿足這個條件,生產者會自動不斷的重試,重試無限次。

2,rabbitmq丟失數據

 比較常見的一個場景,就是kafka某個broker宕機,然後重新選舉partiton的leader時。大家想想,要是此時其他的follower剛好還有些數據沒有同步,結果此時leader掛了,然後選舉某個follower成leader之後,他不就少了一些數據?這就丟了一些數據啊。

所以此時一般是要求起碼設置如下4個參數:

1.給這個topic設置replication.factor參數:這個值必須大於1,要求每個partition必須有至少2個副本

2.在kafka服務端設置min.insync.replicas參數:這個值必須大於1,這個是要求一個leader至少感知到有至少一個follower還跟自己保持聯繫,沒掉隊,這樣才能確保leader掛了還有一個follower吧

3.在producer端設置acks=all:這個是要求每條數據,必須是寫入所有replica之後,才能認爲是寫成功了

4.在producer端設置retries=MAX(很大很大很大的一個值,無限次重試的意思):這個是要求一旦寫入失敗,就無限重試,卡在這裏了

  生產環境就按照上述要求配置的,這樣配置之後,至少在kafka broker端就可以保證在leader所在broker發生故障,進行leader切換時,數據不會丟失

3,消費者丟失數據

唯一可能導致消費者弄丟數據的情況,就是說,你那個消費到了這個消息,然後消費者那邊自動提交了offset,讓kafka以爲你已經消費好了這個消息,其實你剛準備處理這個消息,你還沒處理,你自己就掛了,此時這條消息就丟咯。

  大家都知道kafka會自動提交offset,那麼只要關閉自動提交offset,在處理完之後自己手動提交offset,就可以保證數據不會丟。但是此時確實還是會重複消費,比如你剛處理完,還沒提交offset,結果自己掛了,此時肯定會重複消費一次,自己保證冪等性就好了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章