Kafka精通:Producer發送數據丟失、重複、亂序緣由及解決方案

生產環境對於生產者來講,Kafka集羣發送消息常常會遇到消息丟失、重複、亂序等問題,下面咱們來說解一下出現這些問題的緣由及解決方案。node


1.咱們知道Kafka爲保障數據的可靠性,採用了多副本的存儲機制服務器


    假設一個Topic拆分爲了3個Partition,分別是PartitionA,PartitonB,PartitionC,此時每一個Partition都有2個副本。好比PartitionA有一個副本是leader,另一個副本是follower,leader和follower兩個副本是分佈在不一樣機器上的。網絡

    通常生產環境咱們都會指定Topic的數據有3個副本,即便一臺broker掛掉之後,數據也不會完全丟失,由於其餘broker還存在另外的副本數據。併發


2.副本數據是如何進行同步的呢?異步


    對於多個副本的topic來講,只有分區leader提供讀寫服務的,follower只是不停的嘗試從leader拉取最新的數據到本地,不提供讀寫服務,跟leader數據保持同步的數據有哪些呢?就是經過ISRl來管理的。async

    ISR全稱是「In-Sync Replicas」,就是能跟首領副本基本保持一致的跟隨副本,若是同步的速度太慢的話,就會被踢出ISR副本。ide


3.說一下Kafka的Producer端消息傳遞語義,由參數"acks"控制,分三種:
ui


a.acks=allspa

    意味着當Producer發送消息時,leader接收到消息以後,還必需要求ISR列表裏跟leader保持同步的那些follower都要把消息同步過去,才能認爲這條消息是寫入成功了,這種效率最低,可是可靠性最高。orm


b.acks=1:

    意味着當Producer發送消息時,leader接收到消息並且寫入本地磁盤了,就認爲成功了,無論他其餘的follower有沒有同步過去這條消息了,acks默認值爲1


c.acks=0:

    意味着當Producer發送消息時,producer發送一次就再也不發送了,不論是否發送成功,這種狀況下沒有任何的確認,可能存在消息的丟失;這種效率最高,可是可靠性最低



4.Producer端引發數據丟失、重複、亂序的緣由及解決方案


1).Producer發送數據分爲同步、異步兩種模式,由參數producer.type控制,通常生產採用異步模式批量發送,提升Kafka系統的吞吐率。


a同步模式 producer.type = sync:

    當acks=0,不進行消息接收的確認,那麼當網絡異常時,就會形成數據丟失,通常生產不建議設置爲0;

    當acks=1,在只有leader接收成功併發送ack確認後,leader宕機,副本沒有同步完成,也會形成數據丟失

    上面兩種數據丟失,咱們能夠設置acks=all,保證produce 寫入全部副本算成功,效率比較低。

 producer.type = sync  request.required.acks=all



b.異步模式 producer.type = async:

    異步模式下的有個buffer,經過buffer來進行控制數據的發送,有兩個值來進行控制,時間閾值與消息的數量閾值,若是buffer滿了數據尚未發送出去,若是設置的是當即清理模式,風險很大,容易形成數據丟失。通常設置爲阻塞模式:queue.enqueue.timeout.ms = -1表示後臺消息queue積壓到上限後將一直阻塞,直到queue空間釋放;

producer.type = asyncrequest.required.acks=1queue.buffering.max.ms=6000queue.buffering.max.messages=10000queue.enqueue.timeout.ms = -1batch.num.messages=500


3).acks = all時,數據發送到 leader 後 ,數據發送到 leader 後 ,部分 ISR 的副本同步,leader 此時掛掉。好比 follower1 和 follower2 都有可能變成新的 leader, producer 端會獲得返回異常,producer 端會從新發送數據,可能會形成數據重複,這種可經過冪等性和事務解決,後續會講;


4).acks=all時,當isr列表爲空,若是unclean.leader.election.enable爲true,則會選擇其餘存活的副本做爲新的leader,也會存在消息丟失的問題

可經過設置參數:

unclean.leader.election.enable=false

    這個參數在0.11.0以前其默認值爲true,而以後的版本其默認值爲false。意思是,在leader選舉時是否在沒有活着的ISR副本時從OSR中的最先follower選舉,若是爲true可能會形成數據的丟失;


5).異步發送消息時,有兩條數據數據準備發送到相同的Partition,第一條消息寫入失敗,第二條消息寫入失敗,通過重試後第一批次寫入成功,這時就會形成發送數據的亂序,這種狀況咱們能夠經過設置參數進行限制:

參數:max.in.flight.requests.per.connection

    表示請求隊列大小,默認5,請求隊列中存放的是在發送途中的請求,包括:正在發送的請求和已經發送的但尚未接收到response的請求;請求隊列滿了,發送消息將會發生阻塞。也就是發往同一個node的最大未響應請求。設置此值是1,表示kafka broker在響應請求以前client不能再向同一個broker發送請求,這樣便能夠避免消息亂序

    

    這是我總結的幾種緣由和處理方式,可能不全,後面若是有了新的領悟,我會進行更新和補充。


5.未完待續


    經過4的分析發現kafka在兩端的默認配置都是at least once,可能重複,經過配置也不能作到exactly once,好像kafka的消息必定會丟失或者重複,在kafka 0.11.0.0版本以後,開始引入了冪等性和事務機制來解決上述問題,下一篇文章我將詳細講解冪等性原理及實現剖析。




擴充知識點:

1.Kafka發送數據過快,致使服務器網卡流量暴增。或磁盤過忙,出現丟包,形成。這時候咱們採起如下措施:

     a.首先,對kafka進行限速;

     b.其次啓用重試機制,使重試間隔變長;

     c.Kafka設置ack=all,即須要處於ISR(副本列表)的分區都確認,纔算發送成功。

相關文章
相關標籤/搜索