kafka無消息丟失配置

Kafka只對 “已提交” 的消息(committed message)做有限度的持久化保證;

概念

  • 已提交消息: 當Kafka的若干個 Broker 成功的接收到一跳消息並寫入到日誌系統後,就會通知生產者程序這條消息已提交;
  • 有限度的持久化保證:如果你的消息保存在 N 個 Broker 節點上,那麼持久化的前提就是這 N 個Broker至少有一個節點存活;
    Kafka 是能做到不丟失消息的,只不過這些消息必須是已提交的消息,而且還要滿足一定的條件。當然,說明這件事並不是要爲 Kafka 推卸責任,而是爲了在出現該類問題時我們能夠明確責任邊界。

消息丟失的可能原因

  1. Producer 發送API調用錯誤
Producer 應用向 Kafka發送消息,最後發現Kafka沒有保存;
目前 Kafka Producer 是異步發送消息的,也就是說如果你調用的是 `producer.send(msg)` 這個 API,
那麼它通常會立即返回,但此時你不能認爲消息發送已成功完成。
該API調用如果出現丟失(網絡抖動,消息太大等不合格消息體),生產者是無法感知的;
解決方案:Producer 永遠使用帶有回調通知的發送API:producer.send(msg, callback), 
一旦出現失敗,生產者可提供補救方案。
  1. Broker端宕機
  2. Consumer端丟失數據
`位移`:表示這個Consumer 當前消費到的 Topic分區的位置;
在消費消息的時候,需要先完成對消息的處理;再更新kafka中當前Consumer關於該Topic分區的位移值;
如此帶來新的問題:重複讀;
  1. 多線程場景下,消息丟失
Consumer端採用多線程的方式,異步處理消息;如果某個線程運行失敗;在開啓自動提交位移的情況下會導致消息丟失;
解決方案:
	在該場景下,Consumer端不能啓用自動位移提交,而應該手動提交位移;
	而需要注意的是多線程提交位移實現的正確性;

最佳實踐

  • 不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。記住,一定要使用帶有回調通知的 send 方法。
  • 設置 acks = all。acks 是 Producer 的一個參數,代表了你對“已提交”消息的定義。如果設置成 all,則表明所有副本 Broker 都要接收到消息,該消息纔算是“已提交”。這是最高等級的“已提交”定義。
  • 設置 retries 爲一個較大的值。這裏的 retries 同樣是 Producer 的參數,對應前面提到的 Producer 自動重試。當出現網絡的瞬時抖動時,消息發送可能會失敗,此時配置了 retries > 0 的 Producer 能夠自動重試消息發送,避免消息丟失。
  • 設置 unclean.leader.election.enable = false。這是 Broker 端的參數,它控制的是哪些 Broker 有資格競選分區的 Leader。如果一個 Broker 落後原先的 Leader 太多,那麼它一旦成爲新的 Leader,必然會造成消息的丟失。故一般都要將該參數設置成 false,即不允許這種情況的發生。
  • 設置 replication.factor >= 3。這也是 Broker 端的參數。其實這裏想表述的是,最好將消息多保存幾份,畢竟目前防止消息丟失的主要機制就是冗餘。
  • 設置 min.insync.replicas > 1。這依然是 Broker 端參數,控制的是消息至少要被寫入到多少個副本纔算是“已提交”。設置成大於 1 可以提升消息持久性。在實際環境中千萬不要使用默認值 1。
  • 確保 replication.factor > min.insync.replicas。如果兩者相等,那麼只要有一個副本掛機,整個分區就無法正常工作了。我們不僅要改善消息的持久性,防止數據丟失,還要在不降低可用性的基礎上完成。推薦設置成 replication.factor = min.insync.replicas + 1
  • 確保消息消費完成再提交。Consumer 端有個參數 enable.auto.commit,最好把它設置成false,並採用手動提交位移的方式。就像前面說的,這對於單 Consumer 多線程處理的場景而言是至關重要的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章