發現kafka丟消息後的排查

背景:

      最近在用kafka做消息中間件,producer從hive中讀取消息發送到kafka,後端storm對消息分類發送到elasticsearch建立索引。

問題:

      hive表中總共350萬數據,當時整個全量索引結束後發現,最後索引條數總共310萬左右。storm日誌沒有任何錯誤日誌。

排查:

      首先排查storm consumer的問題,由於發現storm日誌沒有任何異常,所以第一步基本排除建索引程序的問題。storm 消費kafka用的官方storm-kafka包,而且已開啓ack,所以基本排除storm端的問題。

    現在懷疑kafka裏的數據本身只有310萬條數據,寫了一個程序扔到了kafka集羣上探查了一下,印證了自己的想法。果然,數據只有310萬條。現在基本判斷問題的在kafka producer上。仔細查看了下producer代碼

props.put("acks","all");

props.put("retries",3);     

     "acks" 選項表示kafka 的ack級別:acks=0 意味着producer永遠不會等待任何一個來自broker的ack,意味着不需要任何確實,發送及以爲着成功。acks=1 意味着在leader replica已經接收到數據後,producer會得到一個ack,這個選項對速度與安全性做一個平衡,但是不需要等其他副本確認,如果發生leader掛了,其他副本還沒來得及同步,這時就會發生數據丟失的情況。最後一種數據最安全的情況就是acks=al,l意味着在所有的ISR都接收到數據後,producer纔得到一個ack。這個選項提供了最好的持久性,只要還有一個replica存活,那麼數據就不會丟失,但是相應的吞吐量會受到影響。本着對業務對數據可靠性的要求,我選擇了最高的可靠級別,這點沒毛病。

    "retries"選項大於0的值將使客戶端重新發送任何數據,一旦這些數據發送失敗,會間隔一段時間重試,這個值設置的就是重試間隔時間。初步懷疑這個值太小,如果磁盤卡頓,網絡中斷超過三秒,是否會丟數據。所以將這個參數調大到300。

     重新打包上傳到storm集羣重新跑了一回,數據還是丟了30多萬。場面一度尷尬。。問題陷入了僵局。

轉機:

    現在的問題已經超過了我的認知,之前從來沒出現過如此嚴重的丟數據的問題。在網上搜的資料大部分都看過。理論上可靠性可以通過副本解決,沒有類似於我這個種問題。心想着如果不行,只能更改broker 從page cache同步到硬盤的頻率了。鬼使神差下,我更改了下producer的壓縮格式,從snappy改到gzip,這次kafka中的消息,竟然只少了2000。同樣的參數,只改了下壓縮格式。我又查看下了前兩次用snapp格式,kafka裏的消息數,發現了一個問題,兩次用snappy的時候,kafka消息數竟然一模一樣。如果不是玄學的問題,理論上如果丟消息,350萬條,丟相同條數的信息概率簡直太小了。

  現在問題似乎已經很清晰了,gzip壓縮率要比snappy高,snappy優勢在於壓縮速度。壓縮率高意味着單條數據要小。現在基本問題定位在單條數據大小的問題。但是爲什麼producer端沒有異常日誌呢。查看一下producer發送消息的源碼:“Future send(ProducerRecord var1)” producer 發送消息後會發揮一個future,這種模式是異步發送方式,當broker返回異常信息時並不會拋出。,producer.send(producerRecord).get(),加上get(),將異步改同步,打包運行果然發送到30萬條左右數據時就已經拋出異常

kafka.common.MessageSizeTooLargeException

解決:

  至此問題已經定位到,下一步解決問題,搜了下stackoverflow,參考下最高票回答:

Consumer side:fetch.message.max.bytes- this will determine the largest size of a message that can be fetched by the consumer.

Broker side:replica.fetch.max.bytes- this will allow for the replicas in the brokers to send messages within the cluster and make sure the messages are replicated correctly. If this is too small, then the message will never be replicated, and therefore, the consumer will never see the message because the message will never be committed (fully replicated).

Broker side:message.max.bytes- this is the largest size of the message that can be received by the broker from a producer.

Broker side (per topic):max.message.bytes- this is the largest size of the message the broker will allow to be appended to the topic. This size is validated pre-compression. (Defaults to broker'smessage.max.bytes.)



作者:MoCuishle_15b7
鏈接:https://www.jianshu.com/p/ec93eb4f7733
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

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