Kafka生產消費資料丟失和優化小結
我們經常會遇到kafka資料丟失的問題,所以將遇到過的或有可能造成資料丟失的問題進行個小總結。
其實在kafka處理資料的流程有很多,把這些流程梳理一遍,有助於分析資料丟失的情況,從這個圖中可以看出資料流向,圖中涉及的所以過程都可能造成資料的丟失。
- 首先要確定是否有業務資料寫入
- 再明確資料是在kafka之前就已經丟失還是消費端丟失資料的?
2.1 如果是在寫入端丟失資料,那麼每次結果應該完全一樣(在寫入端沒有問題的前提下)。
2.2 如果是在消費端丟失資料,那麼換個消費group重新消費,多次消費結果完全一模一樣的機率很低。
生產階段
丟失問題:若生產時是同步模式,那麼訊息一旦生產,就會阻塞到直到收到server端的確認。但非同步模式下,訊息不會立刻server端,而是在客戶端的緩衝區中進行快取,快取到指定大小或指定時間後,再傳送給server。
所以,若在非同步模式下,業務已經生產了資料,但還沒來得及傳送給server端時,server端就crash了,並且在重傳週期內,server端一直未恢復,那麼此訊息就會丟失。
效能問題:選擇同步模式,雖然很穩妥,但是每次都需要leader再向客戶端傳送確認。這個會降低傳送速度。但選用非同步模式,雖然速度是加快了,但是無法保證準確到達,快取的越多,到達時間會變的久一些,並且快取越大,傳送也可能會變更慢。
優化:在producer端有幾個引數會控制傳送大小和重傳的引數。
- batch.num.messages:每次批量傳送給每個paritition訊息的數量(只對 asyc 起作用)
- request.required.acks:0 表示 producer 不需要等待 leader 的確認,1 代表需要 leader 確認寫入它的本地 log 並立即確認,-1 代表所有的備份都完成後確認(只對 async 起作用)
- queue.buffering.max.ms,預設值:5000,在 producer queue 的快取的資料最大時間(只對 async 起作用)
- queue.buffering.max.message,預設值:10000,producer 快取的訊息的最大數量(只對 async 起作用)
- queue.enqueue.timeout.ms,預設值:-1,0 當 queue 滿時丟掉,負值是 queue 滿時 block, 正值是 queue 滿時 block 相應的時間(只對 async 起作用)
- message.send.max.retries,預設值:3,訊息傳送最大嘗試次數。
- retry.backoff.ms,預設值:300,每次嘗試增加的額外的間隔時間。這個引數不建議在生產環境設的如此小。
broker處
- 即使kafka收到了訊息,仍然可能丟失,因為kafka收到訊息後,並不是立刻落盤,而是存在了快取中,若在此階段kafka異常或磁碟壞掉,那麼此訊息仍會丟失。
解決:修改kafka的配置引數,調整flush到檔案的時間和條數
log.flush.interval.messages=10000
log.flush.interval.ms=3000 - 單批資料的長度超過kafka的限制時,會丟失資料,報kafka.common.MessageSizeTooLargeException異常。
message.max.bytes=20000000(broker能接收訊息的最大位元組數,這個值應該比消費端的fetch.message.max.bytes更小才對,否則broker就會因為消費端無法使用這個訊息而掛起)
fetch.message.max.bytes=20485760
這條配置要符合 client的生產大小<server端可接受的大小<server端可傳送的大小<client的消費大小
消費邏輯
- 在此階段,會批量從server端讀取資料,如果設定自動提交位移,那麼有可能存在還未被業務側讀取,但offset已更新的情況,那麼資料就會丟失:
enable.auto.commit:是否自動提交位移,如果為false,則需要在程式中手動提交位移。 - 關於效能優化
- 啟動的消費執行緒數
- fetch.max.bytes:單次拉取資料的最大位元組數量
- metadata_max_age_ms:強制進行metadata重新整理的週期
- max.poll.records:單次 poll 呼叫返回的最大訊息數,如果處理邏輯很輕量,可以適當提高該值。但是max.poll.records條資料需要在 metadata_max_age_ms這個時間內處理完
總結如下:
在考慮效能問題時,根據資料的特點和要求,需要考慮:
- 是單程式還是多程式生產
- 是同步還是非同步生產,是否需要全部副本都確認
- 調整batch_size的大小,適當增大batch 大小可以來減小網路IO和磁碟IO的請求
- 是否需要多個partiton,分割槽是kafka進行並行讀寫的單位,是提升kafka速度的關鍵。
- 是否需要幾個副本,副本越多,代價就是需要更多資源,尤其是磁碟資源,需要在副本數和可靠性之間平衡
- 是否需要開啟壓縮
- 消費時,是否需要多程式消費
Rebalance問題
在專案中時常遇到rebalance問題,單獨小結一下:
觸發rebalance的條件有三種:
- 組成員發生變更(新 Consumer 加入組、已有 Consumer 主動離開組或已有 Consumer 崩潰了)
- 訂閱主題數發生變更
- 訂閱主題的分割槽數發生變更
我們常遇到的就是consumer沒有和server沒有保持活躍,導致server認為此consumer已退出,所以需要rebalance。而此時offset還未提交,所以會有重複消費的問題。
而沒有保持活躍的原因有多種:
1)處理的執行緒被kill
2)消費者消費太慢,導致超時
3)消費太快,導致消費者處於空poll的狀態,阻塞傳送心跳執行緒;
以上原因都會讓server認為需要rebalance。
優化方案一個是:降低max_poll_records(預設500)或提高metadata_max_age_ms(預設5分鐘強制重新整理metadata)
另一個解決方案是修改heartbeat_interval_ms(預設3秒)和metadata_max_age_ms(預設5分鐘)為差不多的大小,例如將metadata_max_age_ms修改為3s
相關文章
- java的kafka生產消費JavaKafka
- Kafka重複消費和丟失資料研究Kafka
- kafka java 生產消費程式demo示例KafkaJava
- Kafka 架構圖-輕鬆理解 kafka 生產消費Kafka架構
- kafka 如何保證不重複消費又不丟失資料?Kafka
- kafka 消費組功能驗證以及消費者資料重複資料丟失問題說明 3Kafka
- 「Kafka應用」PHP實現生產者與消費者KafkaPHP
- 分享一些 Kafka 消費資料的小經驗Kafka
- 生產消費者模式模式
- 插曲:Kafka的生產者案例和消費者原理解析Kafka
- alpakka-kafka(8)-kafka資料消費模式實現Kafka模式
- 生產者消費者模式模式
- 生產者消費者模型模型
- kafka中生產者和消費者APIKafkaAPI
- kafka消費Kafka
- kafka生產者和消費者吞吐量測試-kafka 商業環境實戰Kafka
- 雲小課|MRS資料分析-透過Spark Streaming作業消費Kafka資料SparkKafka
- 食堂中的生產-消費模型模型
- edenhill/kcat:通用命令列非 JVM Apache Kafka 生產者和消費者命令列JVMApacheKafka
- Kafka 消費組消費者分配策略Kafka
- Eureka:生產環境優化總結。優化
- 使用Flume消費Kafka資料到HDFSKafka
- Kafka - 消費錯誤問題,多臺機器上面無法消費資料Kafka
- 九、生產者與消費者模式模式
- 生產消費實現-寫程式碼
- Spark Streaming 生產、消費流程梳理Spark
- python 生產者消費者模式Python模式
- ActiveMQ 生產者和消費者demoMQ
- kafka_2.11-0.10.2.1 的生產者 消費者的示例(new producer api)KafkaAPI
- SpringBoot整合Kafka(生產者和消費者都是SpringBoot服務)Spring BootKafka
- Kafka 簡單實驗二(Python實現簡單生產者消費者)KafkaPython
- 多執行緒-生產者消費者之等待喚醒機制程式碼優化執行緒優化
- Kafka 消費者解析Kafka
- Kafka - 消費介面分析Kafka
- kafka消費者消費訊息的流程Kafka
- 探索Kafka消費者的內部結構Kafka
- 實際業務處理 Kafka 訊息丟失、重複消費和順序消費的問題Kafka
- Kafka消費者自動提交配置會導致潛在的重複或資料丟失!Kafka