kafka消息丟失的場景分析

一、生產者程序丟失數據

      消息大小超過Broker的message.max.bytes的值,Broker會直接返回錯誤;消息的格式錯誤;網絡的瞬時抖動都可能造成生產者程序的數據沒有發送到Broker;分區首領副本掛了等

      生產者採用producer.send(ProducerRecord record)導致數據發送後不管Broker是否接收到繼續其他業務,都可能會出現上述丟失數據的場景。因此,需要使用producer.send(ProducerRecord record, CallBack callback)發送數據,發送失敗時,Producer可以繼續處理錯誤。

      Producer的max.requests.size表示生產者發送的單個消息的最大值,也可以指單個請求中所有消息的總和大小。此值必須小於Broker的message.max.bytes,能夠有效的避免消息大小超限;網絡抖動導致發送消息瞬時失敗,採用retries+retry.backoff.ms對消息進行重試發送。如果消息是存在順序的,就需要配置max.in.flight.requests.per.connection=1,避免重試帶來的消息亂序。

二、消費者程序丟失數據

      屬性enable.auto.commit決定分區偏移量提交的策略,值爲false時,手動控制提交偏移量。consumer.commitSync()和consumer.commitAsync()、consumer.commitAsync(new OffsetCommitCallBack())分別爲同步提交和異步提交。同步提交會一直重試直到成功,需要Broker的響應,而異步提交能夠提高吞吐量。

      當先提交偏移量,後處理消息時,當消息處理失敗時,該消息將被丟失。

      而當先處理消息,後提交偏移量時,又會出現,consumer突然宕機,導致偏移量提交失敗。或者採用enable.auto.commit=true和auto.commit.intrval.ms自動提交時,consumer宕機,同樣會出現類似問題。這種情況會造成consumer再均衡時,該分區的消息會被重複消費。異步提交時,AB,A第一次提交失敗,B直接提交成功,A再成功,會導致該分區的偏移量偏小,此時consumer宕機,同樣會造成消息被重複消費。

三、Broker丟失數據

      當生產者的acks=1時,表示首領副本的Broker收到消息時,就表示數據已提交。但是,當其他follow副本更新數據前,首領副本宕機,導致該數據就丟失了。因此,acks=all對於消息不可丟失是必須的。unclean.leader.election.enable=false避免非同步副本稱爲新的leader,否則消息肯定就丟失了。

綜上所述,kafka無丟失數據的配置包括:

1、producer.send(msg,callback),而非producer.send(msg)

2、acks=all保證所有副本都收到消息,acks=all不是指Broker的replication.factor的屬性,而是min.insync.replicas的屬性值

3、retries>0保證發送失敗重試

4、unclean.leader.election.enable=false避免非同步的分區成爲leader

5、replication.factor>=3,最好將消息保存3份,min.insync.replicas>1控制消息至少被寫入到多少個副本。replication.factor>min.insync.replicas,如果相等會造成分區不可用。需要改善消息的持久性,防止數據丟失,同時不降低可用性。

6、enable.auto.commit=false手動提交,而非自動提交分區偏移量

 

我有個同學,他們公司,要求消息不被丟失,但是並沒有按照上述配置。採用的是:callback的send、acks=all、retries=3和分區的主動提交。分區主動提交會存在重複消費消息的可能性,但是在業務邏輯中,消息存在唯一key,當key相同時候會直接丟棄,避免了重複消費消息的場景。

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