
2025 年 3 月 18 日,Apache Kafka 4.0 正式發(fā)布。 在此次版本更新中,相較于架構(gòu)層面的升級,開發(fā)者們也應(yīng)關(guān)注一個關(guān)鍵的細節(jié)變更:官方將生產(chǎn)者參數(shù) linger.ms 的默認值,從沿用多年的 0ms 正式修改為 5ms。
這一調(diào)整直擊傳統(tǒng)性能調(diào)優(yōu)的認知盲區(qū),在傳統(tǒng)觀念中,linger.ms=0 意味著“零等待”和實時發(fā)送,通常被視為降低延遲的首選策略。然而,Kafka 4.0 的默認值變更揭示了一個更深層的性能邏輯:在復(fù)雜的網(wǎng)絡(luò) I/O 模型中,單純追求發(fā)送端的實時性并不等同于全局的低延遲。通過引入微小的“人工延遲”來換取更高的批處理效率,往往能顯著降低系統(tǒng)的延遲。
以 Kafka 4.0 的默認值變更為契機,本文將 深入分析 linger.ms 和 batch.size 這兩個核心參數(shù)背后的協(xié)同機制。幫助你在面對復(fù)雜的生產(chǎn)環(huán)境時,基于原理掌握 linger.ms 和 batch.size 的最佳實踐。
1 linger.ms 和 batch.size 參數(shù)
為了透徹理解這次變更背后的深層邏輯,首先我們需要回歸基礎(chǔ),準確理解這兩個核心參數(shù)的概念。
linger.ms
生產(chǎn)者會將兩次請求傳輸之間到達的所有記錄組合成單一的批處理請求。這種攢批行為通常在記錄到達速率超過發(fā)送速率的高負載場景下自然發(fā)生,但在負載適中時,客戶端也可通過配置 linger.ms 引入少量的“人為延遲”來主動減少請求數(shù)量。其行為邏輯類似于 TCP 協(xié)議中的 Nagle 算法:生產(chǎn)者不再立即發(fā)送每一條到達的記錄,而是等待一段指定的時間以聚合更多后續(xù)記錄。該設(shè)置定義了批處理的時間上限,發(fā)送行為遵循“先滿足者優(yōu)先”原則——一旦分區(qū)積累的數(shù)據(jù)量達到 batch.size,無論 linger.ms 是否到期,批次都會立即發(fā)送;反之,若數(shù)據(jù)量不足,生產(chǎn)者將“逗留”指定時長以等待更多記錄。在 Apache Kafka 4.0 中,該參數(shù)的默認值已從 0ms 調(diào)整為 5ms,其依據(jù)在于更大批次帶來的效率增益通常足以抵消引入的等待時間,從而實現(xiàn)持平甚至更低的整體生產(chǎn)者延遲。
batch.size
當(dāng)多條記錄需發(fā)往同一分區(qū)時,生產(chǎn)者會將這些記錄聚合為批次(Batch)以減少網(wǎng)絡(luò)請求頻率,從而優(yōu)化客戶端與服務(wù)端的 I/O 性能。batch.size 參數(shù)定義了該批次的默認容量上限(以字節(jié)為單位),超過該閾值的單條記錄將不被納入批處理邏輯。發(fā)往 Broker 的單個請求通常包含多個批次,分別對應(yīng)不同的分區(qū)。配置過小的 batch.size 會限制批處理的發(fā)生頻率并可能降低吞吐量(設(shè)置為 0 將完全禁用批處理);而過大的配置則可能因生產(chǎn)者總是基于此閾值預(yù)分配緩沖區(qū)而導(dǎo)致內(nèi)存資源的輕微浪費。該設(shè)置確立了發(fā)送行為的空間上限:若當(dāng)前分區(qū)積累的數(shù)據(jù)量未達到此閾值,生產(chǎn)者將依據(jù) linger.ms(默認為 5ms)的設(shè)定進行等待;發(fā)送觸發(fā)邏輯遵循“先滿足者優(yōu)先(Whichever happens first)”原則,即一旦數(shù)據(jù)量填滿緩沖區(qū)或等待時間耗盡,批次即會被發(fā)送。需要注意的是,Broker 端的背壓可能導(dǎo)致實際的有效等待時間超過配置值。
通過對兩個維度的拆解,我們可以清晰地看到 linger.ms 和 batch.size 的協(xié)同工作模式:
它們共同決定了 RecordBatch(批次)的大小和 ProduceRequest(請求)的發(fā)送時機。
linger.ms 和 batch.size 參數(shù)值較大 -> RecordBatch 和 ProduceRequest 批處理效果越好 -> Kafka 服務(wù)器需要處理的 RPC 數(shù)量更少 -> Kafka 服務(wù)端 CPU 消耗越低。
副作用:客戶端在批處理上花費的時間增加,從而導(dǎo)致客戶端的發(fā)送延遲變高。
這引出了一個關(guān)鍵的性能權(quán)衡問題:
“在服務(wù)端 CPU 資源充足的前提下,為了追求極致的低延遲。是否應(yīng)當(dāng)盡可能最小化 linger.ms 和 batch.size?”
基于直覺的推斷,答案似乎是肯定的。然而,Kafka 4.0 的官方文檔指出了相反的結(jié)論:
“Apache Kafka 4.0 將默認值從 0 調(diào)整為 5。盡管增加了人為的等待時間,但更大批次帶來的處理效率提升,通常會導(dǎo)致相似甚至更低的生產(chǎn)者延遲。”
inger.ms=0 代表即時發(fā)送,為什么在延遲的表現(xiàn)上反而不如“先等待 5ms”?
2 Kafka 服務(wù)端與客戶端交互的底層規(guī)則
要透徹理解這一反直覺的性能表現(xiàn),我們不能僅停留在客戶端配置的表面,而必須深入 Apache Kafka 網(wǎng)絡(luò)協(xié)議的底層。延遲的產(chǎn)生,本質(zhì)上源于客戶端發(fā)送策略與服務(wù)端處理模型之間的交互機制。為了探究其根源,我們需要分別從服務(wù)端和客戶端兩個維度,解析這套底層規(guī)則的運作邏輯。
服務(wù)端視角:嚴格按序的“串行”模式
Kafka 的網(wǎng)絡(luò)協(xié)議在設(shè)計上與 HTTP 1.x 頗為相似,它采用的是一種嚴格的順序且串行的工作模式。這是理解所有延遲問題的基石:
順序性(Sequential): 對于來自同一個 TCP 連接的請求,服務(wù)端必須嚴格按照接收到的順序進行處理,并按同樣的順序返回響應(yīng)。
串行性(Serial):服務(wù)端只有在完全處理完當(dāng)前請求并發(fā)送響應(yīng)后,才會開始處理下一個請求。即便客戶端并發(fā)發(fā)送 N 個 ProduceRequest,服務(wù)端也會嚴格執(zhí)行‘One-by-One’策略:必須等到前一個請求的數(shù)據(jù)完成所有 ISR 副本同步并返回響應(yīng)后,才會開始處理下一個請求。
這意味著:哪怕客戶端一股腦地并發(fā)發(fā)送了 N 個 ProduceRequest,服務(wù)端也不會并行處理。如果前一個請求因為 ISR 同步卡頓了,后續(xù)的所有請求都只能在服務(wù)端排隊等候。
![]()
客戶端視角:化解擁堵的“Batch”原理
在客戶端側(cè),Producer 的批處理主要包含兩個核心模塊:RecordAccumulator 和 Sender,分別對應(yīng) RecordBatch 和 ProduceRequest。
RecordAccumulator:負責(zé)將 RecordBatch 進行批處理。KafkaProducer 將記錄放入 RecordAccumulator 進行批處理。當(dāng)分區(qū)內(nèi)的 ProduceBatch 數(shù)據(jù)超過 batch.size 時,它會切換到下一個分區(qū)并創(chuàng)建一個新的 ProduceBatch 進行批處理。
Sender:負責(zé)維護與服務(wù)器節(jié)點的連接并分批發(fā)送數(shù)據(jù)。它會基于節(jié)點從 RecordAccumulator 中排干就緒分區(qū)的數(shù)據(jù),將它們打包成 ProduceRequest 并發(fā)送。排干需要同時滿足以下條件:
連接上的在途請求數(shù)量小于 max.in.flight.requests.per.connection=5
對應(yīng)節(jié)點的任何 ProduceBatch 超過 linger.ms 或超過 batch.size
3 場景推演:0ms 與 5ms 的性能對比
基于上述原理,我們需要進一步評估該機制在實際場景中的表現(xiàn)。當(dāng)客戶端配置 linger.ms=0 以執(zhí)行即時發(fā)送策略,而服務(wù)端受限于串行處理模型時,供需兩側(cè)的處理節(jié)奏將產(chǎn)生錯配。為了準確判斷這種錯配究竟是降低了延遲還是引發(fā)了排隊積壓,僅憑定性分析不足以說明問題。接下來,我們將構(gòu)建一個模型,通過場景化的定量推演,計算不同配置下的具體延遲數(shù)據(jù)。
場景假設(shè):
部署一個單節(jié)點集群,創(chuàng)建一個包含 10 個分區(qū)的 Topic。
客戶端:單客戶端,發(fā)送速率 1000 條記錄 / 秒,記錄大小 1KB。
服務(wù)端:處理一個 ProduceRequest 耗時 5ms。
對比組:
配置 A:linger.ms=0,batch.size=16KB(Apache Kafka 4.0 之前的默認配置)
配置 B:linger.ms=5,其余不變(4.0 新版默認)
推演 A:當(dāng) linger.ms = 0
1,000 records/s意味著每 1ms 調(diào)用一次 KafkaProducer;
由于 linger.ms=0,前 5 條記錄會立即轉(zhuǎn)換為 5 個 ProduceRequest,分別在時間戳 T=0ms,T=0.1ms, ...,T=0.4ms 發(fā)送。
Apache Kafka 順序且串行地處理這 5 個 ProduceRequest:
T=5ms:Apache Kafka 完成第 1 個 ProduceRequest 的請求,返回響應(yīng),并開始處理下一個 ProduceRequest;
T=10ms:第 2 個 ProduceRequest 處理完畢,開始處理下一個;
以此類推,第 5 個 ProduceRequest 在 T=25ms 時處理完畢。
T=5ms:客戶端收到第 1 個 ProduceRequest 的響應(yīng),滿足 inflight.request < 5 的條件,從 RecordAccumulator 排干數(shù)據(jù)。此時,內(nèi)存中已積累了 (5 - 0.4) / 1 ~= 4K 的數(shù)據(jù),這些數(shù)據(jù)將被放入一個 ProduceRequest 中,Sender 將其打包成第 6 個請求發(fā)出。
T=30ms:Apache Kafka 在 T=25ms 處理完第 5 個請求后,接著處理第 6 個請求,并在 T=30ms 返回響應(yīng)。
T=10ms:同樣地,收到第 2 個 ProduceRequest 的響應(yīng)后,客戶端積累了 (10 - 5) / 1 = 5K 的數(shù)據(jù)并發(fā)送給 Broker。Apache Kafka 在 T=35ms 返回響應(yīng)。
以此類推,后續(xù)的 ProduceRequest 都會在 T1 時刻積累 5K 數(shù)據(jù)并發(fā)送給 Broker,Broker 會在 T1 + 25ms 響應(yīng)請求。平均生產(chǎn)延遲為 5ms / 2 + 25ms = 27.5ms。(5ms / 2 是平均批處理時間)。
推演 B:當(dāng) linger.ms = 5
T=5ms:由于 linger.ms=5,客戶端會先積攢數(shù)據(jù)直到 5ms,然后發(fā)出第一個 ProduceRequest。服務(wù)端會在 T=10ms 時對該請求做出響應(yīng)。
T=10ms:由于 linger.ms=5,客戶端會繼續(xù)積攢新數(shù)據(jù)達 5ms,隨后發(fā)出第二個 ProduceRequest。服務(wù)端會在 T=15ms 時做出響應(yīng)。
以此類推: 后續(xù)的請求都會在 T1 時刻攢夠 5K 數(shù)據(jù)后發(fā)往 Broker,Broker 會在 T1 + 5ms 時做出響應(yīng)。此時的平均生產(chǎn)延遲計算如下:5ms / 2 + 5ms = 7.5ms(注:5ms / 2 代表平均攢批的時間)。
在這個假設(shè)場景中,雖然我們將 linger.ms 從 0 ms 增加到 5 ms,但平均生產(chǎn)延遲反而從 27.5 ms 降到了 7.5 ms。由此可見,“l(fā)inger.ms 越小,延遲越低”這一說法并不絕對成立。
4 linger.ms 與 batch.size 配置最佳實踐
通過對比 linger.ms 為 0ms 和 5ms 的情況,我們可以得出結(jié)論:客戶端的主動批處理,將 在途請求控制在 1 及以內(nèi),要比快速把請求發(fā)出然后在網(wǎng)絡(luò)層排隊,更能降低生產(chǎn)延遲。
那么如何在千變?nèi)f化的生產(chǎn)環(huán)境中,精準設(shè)定這兩個參數(shù)的閾值?
我們需要一套科學(xué)的計算公式,根據(jù)服務(wù)端的實際處理能力,倒推客戶端的最佳配置。以下是針對最小化生產(chǎn)延遲的定向配置建議:
linger.ms >= 服務(wù)端處理耗時。
如果 linger.ms 小于網(wǎng)絡(luò)耗時和服務(wù)端的處理時間,根據(jù) Kafka 網(wǎng)絡(luò)協(xié)議的串行處理模式,發(fā)出的 ProduceRequests 就會在網(wǎng)絡(luò)層產(chǎn)生積壓。這違背了我們前面提到的“將網(wǎng)絡(luò)在途請求數(shù)控制在 1 及以內(nèi)”的原則。
batch.size >= (單個客戶端最大寫入吞吐量) * (linger.ms / 1000) / (Broker 數(shù)量)。
如果 batch.size 未設(shè)置為大于或等于此值,則意味著在達到 linger.ms 之前,由于 ProduceBatch 超過 batch.size,將會被迫提前發(fā)送請求。同樣,這些 ProduceRequest 無法及時處理,將在網(wǎng)絡(luò)中排隊,違反了 “將網(wǎng)絡(luò)在途請求數(shù)控制在 1 及以內(nèi)”的原則。
建議將 batch.size 設(shè)置得盡可能大(例如 256K):
linger.ms 是基于服務(wù)端的平均生產(chǎn)延遲來設(shè)定的。一旦服務(wù)端出現(xiàn)性能抖動(Jitter),更大的 batch.size 允許我們在單個 RecordBatch 中積攢更多數(shù)據(jù),從而避免因為拆分成多個小請求發(fā)送而導(dǎo)致整體延遲升高。
以單節(jié)點集群為例,假設(shè)服務(wù)器處理一個 ProduceRequest 需要 5ms。那么我們需要將 linger.ms 設(shè)置為至少 5ms。如果我們預(yù)期單個生產(chǎn)者的發(fā)送速度能達到 10MBps,那么 batch.size 應(yīng)設(shè)置為至少 10 * 1024 *(5 / 1000)= 51.2K。
5 從“客戶端攢批”走向“服務(wù)端流水線”
Apache Kafka 4.0 對默認值的調(diào)整,驗證了一個核心的技術(shù)共識:在處理大規(guī)模數(shù)據(jù)流時,適度的批處理是平衡吞吐與延遲的有效手段。這是一種基于客戶端視角的成熟優(yōu)化策略。
然而,性能優(yōu)化的路徑不止一條。既然瓶頸在于服務(wù)端的“串行處理”,那么除了一味調(diào)整客戶端參數(shù)外,我們是否可以從服務(wù)端本身尋求突破?正是基于這一思考,作為云原生 Kafka 的探索者,AutoMQ 嘗試從服務(wù)端視角尋找新的突破:在完全兼容 Kafka 協(xié)議語義的前提下,AutoMQ 引入了“Pipeline(流水線)機制”。這一機制并非改變協(xié)議本身,而是優(yōu)化了服務(wù)端的模型,使得在保證順序性的同時,能夠充分利用云原生存儲的并發(fā)能力,將 ProduceRequest 的處理效率提升了 5 倍。
![]()
這意味著什么?讓我們回到之前的推演場景:
即便在 linger.ms=0 導(dǎo)致多個在途請求積壓的情況下,AutoMQ 的流水線機制允許服務(wù)端同時處理這些請求,顯著降低了排隊延遲:
Apache Kafka:由于串行排隊,平均延遲達 27.5ms。
AutoMQ:憑借流水線機制,平均延遲降至 7.5ms。
因此,當(dāng)使用 AutoMQ 作為服務(wù)端時,你可以享受服務(wù)端處理效率的 5 倍提升,客戶端不再需要通過長時間的“逗留”來遷就服務(wù)端,從而獲得更低的延遲體驗。你可以將參數(shù)配置為原建議值的 1/5,linger.ms 的配置策略會與 Apache Kafka 略有不同:
linger.ms >= (服務(wù)端處理耗時 / 5)
batch.size >= (單個客戶端最大寫入吞吐量) * (linger.ms / 1000) / (Broker 數(shù)量)
(注:同樣建議在內(nèi)存允許范圍內(nèi),將 batch.size 盡可能調(diào)大,如 256K)
這種配置上的差異,揭示了性能優(yōu)化視角的轉(zhuǎn)變:要做到性能調(diào)優(yōu),不能僅依賴于客戶端的適配。
AutoMQ 通過架構(gòu)層面的創(chuàng)新實踐,讓用戶無需在“低延遲”和“高吞吐”之間做艱難的權(quán)衡,而是以更低的門檻實現(xiàn)了兩者的兼得。技術(shù)總是在不斷演進的。從參數(shù)調(diào)優(yōu)走向架構(gòu)演進,不僅是 AutoMQ 的選擇,也是云原生時代消息中間件發(fā)展的方向。
6 結(jié)語
感謝您讀到這里。
本文回顧了 Apache Kafka 4.0 中 linger.ms 與 batch.size 參數(shù)的配置,指出了在傳統(tǒng)串行網(wǎng)絡(luò)模型下,客戶端進行性能調(diào)優(yōu)時所面臨的“延遲與吞吐”權(quán)衡難題。隨后,我們深入解析了 AutoMQ 的 Pipeline 機制,它通過服務(wù)端 I/O 模型的重構(gòu),解除了順序處理與串行執(zhí)行的強綁定。
Pipeline 機制是 AutoMQ 云原生架構(gòu)的核心特性之一,無需依賴繁瑣的客戶端參數(shù)調(diào)整,即可在保證數(shù)據(jù)嚴格順序的前提下,實現(xiàn) 5 倍于傳統(tǒng)架構(gòu)的處理效率。結(jié)合對云原生存儲的深度適配,AutoMQ 致力于通過底層架構(gòu)的演進,助力企業(yè)以更簡的運維構(gòu)建極致性能的流數(shù)據(jù)平臺。
感謝您的閱讀,我們下篇文章再見。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.