本文主要介紹消息隊列 Kafka 發布者的最佳實踐,從而幫助您更好的使用該產品。
文中的最佳實踐基于消息隊列 Kafka 的 Java 客戶端;對于其它語言的客戶端,其基本概念與思想是通用的,但實現細節可能有差異,僅供參考。
Kafka 發送示例代碼片段

Key 和 Value
Kafka 0.10.0.0 的消息字段只有兩個:Key 和 Value。Key 是消息的標識,Value 即消息內容。為了便于追蹤,重要消息最好都設置一個唯一的 Key。通過 Key 追蹤某消息,打印發送日志和消費日志,了解該消息的發送和消費情況。
失敗重試
在分布式環境下,由于網絡等原因,偶爾的發送失敗是常見的。導致這種失敗的原因有可能是消息已經發送成功,但是 Ack 失敗,也有可能是確實沒發送成功。
消息隊列 Kafka 是 VIP 網絡架構,會主動掐掉空閑連接(30 秒沒活動),也就是說,不是一直活躍的客戶端會經常收到 “connection rest by peer” 這樣的錯誤,因此建議都考慮重試消息發送。
異步發送
發送接口是異步的;如果你想得到發送的結果,可以調用metadataFuture.get(timeout, TimeUnit.MILLISECONDS)。
線程安全
Producer 是線程安全的,且可以往任何 Topic 發送消息。通常情況下,一個應用對應一個 Producer 就足夠了。
Acks
Acks的說明如下:
- acks=0,表示無需服務端的 Response,性能較高,丟數據風險較大;
- acks=1,服務端主節點寫成功即返回 Response,性能中等,丟數據風險中等,主節點宕機可能導致數據丟失;
- acks=all,服務端主節點寫成功,且備節點同步成功,才返回 Response,性能較差,數據較為安全,主節點和備節點都宕機才會導致數據丟失。
一般建議選擇 acks=1,重要的服務可以設置 acks=all。
Batch
Batch 的基本思路是:把消息緩存在內存中,并進行打包發送。Kafka 通過 Batch 來提高吞吐,但同時也會增加延遲,生產時應該對兩者予以權衡。
在構建 Producer 時,需要考慮以下兩個參數:
- batch.size : 發往每個分區(Partition)的消息緩存量(消息內容的字節數之和,不是條數)達到這個數值時,就會觸發一次網絡請求,然后客戶端把消息真正發往服務器;
- linger.ms : 每條消息待在緩存中的最長時間。若超過這個時間,就會忽略 batch.size 的限制,然后客戶端立即把消息發往服務器。
由此可見,Kafka 客戶端什么時候把消息真正發往服務器,是通過上面兩個參數共同決定的。batch.size 有助于提高吞吐,linger.ms有助于控制延遲。您可以根據具體業務需求進行調整。
OOM
結合 Kafka 的 Batch 設計思路,Kafka 會緩存消息并打包發送,如果緩存太多,則有可能造成 OOM(Out of Memory)。
- buffer.memory : 所有緩存消息的總體大小超過這個數值后,就會觸發把消息發往服務器。此時會忽略 batch.size 和 linger.ms 的限制。
- buffer.memory 的默認數值是 32 MB,對于單個 Producer 來說,可以保證足夠的性能。需要注意的是,如果你在同一個 JVM 中啟動多個 Producer,那么每個 Producer 都有可能占用 32 MB 緩存空間,此時便有可能觸發 OOM。
在生產時,一般沒有必要啟動多個 Producer;如果特殊情況需要,則需要考慮buffer.memory的大小,避免觸發 OOM。