前言
在前面文章《Kafka精進 | 一文讀懂Producer消息發送機制》中,我們從Kafka消息結構、序列化器、分區器及消息緩沖池等方面介紹了Producer端的原理,回顧示意圖如下:

實際使用中,Producer端既要保證吞吐量,又要確定無消息丢失,一些核心參數的配置顯得至關重要。本文我們就來看看生産端都有哪些重要的參數。
生産端核心參數
1. acks
參數說明:這是一個非常重要的參數,表示指定分區中成功寫入消息的副本數量,這是Kafka生産端消息的持久性(durability)保證。隻有當leader确認已成功寫入消息的副本數後,才會給Producer發送響應,此時消息才可以認為“已送出”。該參數影響着消息的可靠性以及生産端的吞吐量,并且兩者往往相向而馳,通常消息可靠性越高則生産端的吞吐量越低,反之亦然。acks有3個取值:
- acks = 0:表示生産端發送消息後立即傳回,不等待broker端的響應結果。通常此時生産端吞吐量最高,消息發送的可靠性最低。
- acks = 1: 表示leader副本成功寫入就會響應Producer,而無需等待ISR(同步副本)集合中的其他副本寫入成功。這種方案提供了适當的持久性,保證了一定的吞吐量。預設值即是1。
- acks = all或-1: 表示不僅要等leader副本成功寫入,還要求ISR中的其他副本成功寫入,才會響應Producer。這種方案提供了最高的持久性,但也提供了最差的吞吐量。
調優建議:建議根據實際情況設定,如果要嚴格保證消息不丢失,請設定為all或-1;如果允許存在丢失,建議設定為1;一般不建議設為0,除非無所謂消息丢不丢失。
2. max.request.size
參數說明:這個參數比較重要,表示生産端能夠發送的最大消息大小,預設值為1048576,即1M。
調優建議:一般而言,這個配置有點小,為了避免因消息過大導緻發送失敗,建議适當調大,比如調到10485760即10M。
3. retries
參數說明:表示生産端消息發送失敗時的重試次數,預設值為0,表示不進行重試。這個參數一般是為了解決因瞬時故障導緻的消息發送失敗,比如網絡抖動、leader換主,其中瞬時的leader重選舉是比較常見的。是以這個參數的設定顯得非常重要。
另外為了避免頻繁重試的影響,兩次重試之間都會停頓一段時間,受參數retry.backoff.ms,預設為100ms,通常可以不調整。
調優建議:這裡要盡量避免消息丢失,建議設定為一個大于0的值,比如3或者更大值。
4. compression.type
參數說明:表示生産端是否對消息進行壓縮,預設值為none,即不壓縮消息。壓縮可以顯著減少網絡IO傳輸、磁盤IO以及磁盤空間,進而提升整體吞吐量,但也是以犧牲CPU開銷為代價的。目前Kafka支援4種壓縮方式,分别是gzip、snappy、lz4 及 zstd(Kafka 2.1.0開始支援)。
調優建議:出于提升吞吐量的考慮,建議在生産端對消息進行壓縮。對于Kafka而已,綜合考慮吞吐量與壓縮比,建議選擇lz4壓縮。如果追求最高的壓縮比則推薦zstd壓縮。
5. buffer.memory
參數說明:表示生産端消息緩沖池或緩沖區的大小,預設值為33554432,即32M。這個參數基本可以認為是Producer程式所使用的記憶體大小。
目前版本中,如果生産消息的速度過快導緻buffer滿了的時候,将阻塞max.block.ms(預設60000即60s)配置的時間,逾時将會抛TimeoutException異常。在Kafka 0.9.0及之前版本,建議設定另一個參數block.on.buffer.full為true,該參數表示當buffer填滿時Producer處于阻塞狀态并停止接收新消息而不是抛異常。
調優建議:通常我們應盡量保證生産端整體吞吐量,建議适當調大該參數,也意味着生産用戶端會占用更多的記憶體。也可以選擇不調整。
6. batch.size
參數說明:發送到緩沖區中的消息會被分為一個一個的batch,分批次的發送到broker 端,這個參數就表示batch批次大小,預設值為16384,即16KB。是以減小batch大小有利于降低消息延時,增加batch大小有利于提升吞吐量。
調優建議:通常合理調大該參數值,能夠顯著提升生産端吞吐量,比如可以調整到32KB,調大也意味着消息會有相對較大的延時。
7. linger.ms
參數說明:用來控制batch最大的空閑時間,超過該時間的batch也會被發送到broker端。這實際上是一種權衡,即吞吐量與延時之間的權衡。預設值為0,表示消息需要被立即發送,無需關系batch是否被填滿。
調優建議:通常為了減少請求次數、提升整體吞吐量,建議設定一個大于0的值,比如設定為100,此時會在負載低的情況下帶來100ms的延時。
8. request.timeout.ms
參數說明:這個參數表示生産端發送請求後等待broker端響應的最長時間,預設值為30000,即30s,逾時生産端可能會選擇重試(如果配置了retries)。
調優建議:該參數預設值一般夠用了。如果生産端負載很大,可以适當調大以避免逾時,比如可以調到60000。
9. max.in.fight.requests.per.connection
參數說明:這個參數非常重要,表示生産端與broker之間的每個連接配接最多緩存的請求數,預設值為5,即每個連接配接最多可以緩存5個未響應的請求。這個參數通常用來解決分區亂序的問題。
調優建議:為了避免消息亂序問題,建議将該參數設定為1,表示生産端在某個broker響應之前将無法再向該broker發送消息請求,這能夠有效避免同一分區下的消息亂序問題。
無消息丢失配置
本文開始我們提到,Producer既要保證吞吐量,又要確定無消息丢失。結合上面的參數介紹,這裡給出消息無丢失的配置清單,如下:
- acks = all or -1
- retries = 3
- max.in.fight.requests.per.connection = 1
- 使用帶回調機制的send方法即send(record, callback)發送消息,并對失敗消息進行處理
- unclean.leader.election.enable = false
- replication.factor = 3
- min.insync.replicas = 2
- enable.auto.commit = false
前3個參數本文已介紹。最後一個是消費端參數,表示禁用自動送出,後面我們再介紹。其他幾個屬于broker端的參數。
其中比較難了解的是min.insync.replicas,這個參數表示ISR集合中的最少副本數,預設值是1,并隻有在acks=all或-1時才有效。acks與min.insync.replicas搭配使用,才能為消息提供最高的持久性保證。我們知道leader副本預設就包含在ISR中,如果ISR中隻有1個副本,acks=all也就相當于acks=1了,引入min.insync.replicas的目的就是為了保證下限:不能隻滿足于ISR全部寫入,還要保證ISR中的寫入個數不少于min.insync.replicas。常見的場景是建立一個三副本(即replication.factor=3)的topic,最少同步副本數設為2(即min.insync.replicas=2),acks設為all,以保證最高的消息持久性。
總結
至此生産端重要的參數基本介紹完了。總結起來,本文首先介紹了Producer端的核心參數,說明參數含義的同時并給出了調優建議,最後給出了一份消息無丢失的參數配置清單供參考。更多生産端參數介紹可以參考Kafka官網http://kafka.apache.org/documentation/#producerconfigs。