高并發場景下,Kafka如何抗住億級流量?
順序寫磁盤
Kafka 之所以能夠實現高吞吐量,順序寫磁盤是其核心優化策略之一。
如下圖所示:
最新文章
Partition-0
├──00000000000000000000.log
├──00000000000000000000.index
├──00000000000000000000.timeindex
├──00000000000000000100.log
├──...
Kafka中每個主題分區對應一個日志文件(Log),消息以二進制形式順序寫入該文件。
并為每條消息分配唯一偏移量(offset),用于定位和順序讀取。
新的消息總是被追加到日志文件的末尾,就像寫日志一樣,只能在文件尾部添加新的記錄。
順序寫入時,磁頭只需要很少的移動,甚至可以認為是“步進式”地寫入,避免了隨機寫入時大量的磁頭移動,從而顯著提升寫入速度。
Page Cache
Kafka 寫入消息時,并不是立刻將數據同步寫入磁盤,而是先寫入操作系統的 PageCache,再由操作系統異步刷盤。
這種設計實現了高吞吐 + 可持久化保障的完美平衡。
如下圖所示:
最新文章
Producer-->KafkaBroker(接收消息)-->寫入內存頁緩存(PageCache)-->刷寫到磁盤文件(*.log)
Page Cache :是操作系統內核利用空閑的物理內存,來緩存最近訪問過的磁盤數據。
當應用程序寫入文件時,數據首先被寫入到 Page Cache 中,這個過程是在內存中完成的,速度非??臁?/span>
為什么快?
因為寫入內存(Page Cache),比直接寫入磁盤要快得多。
KafkaProducer 將消息發送到 Broker,Broker 將消息追加到其分區日志文件的 Page Cache 中。
從而,無需等待磁盤 I/O 完成,從而實現了高吞吐量的寫入。
零拷貝
當 Broker ,需要將消息發送給 Consumer 時,Kafka 利用操作系統的零拷貝技術(如 sendfile
)。
// Kafka 的 FileRecords 類中
channel.transferTo(position, count, targetChannel);
最新文章
底層調用的就是 FileChannel.transferTo()
,而這在 Linux 上最終就是 sendfile
。
這允許數據直接從 Page Cache ,復制到網絡套接字緩沖區,而無需經過 Kafka Broker 的用戶空間。
磁盤→內核緩沖區→網卡
(中間不經過用戶態,少兩次拷貝)
從而,減少了數據拷貝的次數和上下文切換,顯著提高了網絡傳輸效率并降低了 CPU 開銷。
批量發送
Kafka Producer 會將多個消息打包成一個批次進行發送,Consumer 也會批量地拉取消息。
最新文章
這種批量處理的方式可以減少網絡請求的次數,降低網絡開銷,并提高吞吐量。