Kafka 為什么能那么快的 6 個原因

1. 利用 Partition 實現(xiàn)并行處理



2. 順序?qū)懘疟P

3. 充分利用 Page Cache
I/O Scheduler 會將連續(xù)的小塊寫組裝成大塊的物理寫從而提高性能 I/O Scheduler 會嘗試將一些寫操作重新按順序排好,從而減少磁盤頭的移動時間 充分利用所有空閑內(nèi)存(非 JVM 內(nèi)存)。如果使用應用層 Cache(即 JVM 堆內(nèi)存),會增加 GC 負擔 讀操作可直接在 Page Cache 內(nèi)進行。如果消費和生產(chǎn)速度相當,甚至不需要通過物理磁盤(直接通過 Page Cache)交換數(shù)據(jù) 如果進程重啟,JVM 內(nèi)的 Cache 會失效,但 Page Cache 仍然可用
flush.messages 和 flush.ms 兩個參數(shù)將 Page Cache 中的數(shù)據(jù)強制 Flush 到磁盤,但是 Kafka 并不建議使用。4. 零拷貝技術
網(wǎng)絡數(shù)據(jù)持久化到磁盤 (Producer 到 Broker) 磁盤文件通過網(wǎng)絡發(fā)送(Broker 到 Consumer)
4.1 網(wǎng)絡數(shù)據(jù)持久化到磁盤 (Producer 到 Broker)
data = socket.read()// 讀取網(wǎng)絡數(shù)據(jù)File file = new File()file.write(data)// 持久化到磁盤file.flush()
首先通過 DMA copy 將網(wǎng)絡數(shù)據(jù)拷貝到內(nèi)核態(tài) Socket Buffer 然后應用程序?qū)?nèi)核態(tài) Buffer 數(shù)據(jù)讀入用戶態(tài)(CPU copy) 接著用戶程序?qū)⒂脩魬B(tài) Buffer 再拷貝到內(nèi)核態(tài)(CPU copy) 最后通過 DMA copy 將數(shù)據(jù)拷貝到磁盤文件

特殊場景下:接收來自 socket buffer 的網(wǎng)絡數(shù)據(jù),應用進程不需要中間處理、直接進行持久化時??梢允褂?mmap 內(nèi)存文件映射。producer.type 來控制是不是主動flush;如果 Kafka 寫入到 mmap 之后就立即 flush 然后再返回 Producer 叫同步(sync);寫入 mmap 之后立即返回 Producer 不調(diào)用 flush 就叫異步(async),默認是 sync。
直接I/O:數(shù)據(jù)直接跨過內(nèi)核,在用戶地址空間與I/O設備之間傳遞,內(nèi)核只是進行必要的虛擬存儲配置等輔助工作; 避免內(nèi)核和用戶空間之間的數(shù)據(jù)拷貝:當應用程序不需要對數(shù)據(jù)進行訪問時,則可以避免將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間 mmap sendfile splice && tee sockmap copy on write:寫時拷貝技術,數(shù)據(jù)不需要提前拷貝,而是當需要修改的時候再進行部分拷貝。
4.2 磁盤文件通過網(wǎng)絡發(fā)送(Broker 到 Consumer)
buffer = File.readSocket.send(buffer)
首先通過系統(tǒng)調(diào)用將文件數(shù)據(jù)讀入到內(nèi)核態(tài) Buffer(DMA 拷貝) 然后應用程序?qū)?nèi)存態(tài) Buffer 數(shù)據(jù)讀入到用戶態(tài) Buffer(CPU 拷貝) 接著用戶程序通過 Socket 發(fā)送數(shù)據(jù)時將用戶態(tài) Buffer 數(shù)據(jù)拷貝到內(nèi)核態(tài) Buffer(CPU 拷貝) 最后通過 DMA 拷貝將數(shù)據(jù)拷貝到 NIC Buffer

transferTo/transferFrom 調(diào)用操作系統(tǒng)的 sendfile 實現(xiàn)零拷貝??偣舶l(fā)生 2 次內(nèi)核數(shù)據(jù)拷貝、2 次上下文切換和一次系統(tǒng)調(diào)用,消除了 CPU 數(shù)據(jù)拷貝5. 批處理
6. 數(shù)據(jù)壓縮
小總結 | 下次面試官問我 kafka 為什么快,我就這么說
partition 并行處理 順序?qū)懘疟P,充分利用磁盤特性 利用了現(xiàn)代操作系統(tǒng)分頁存儲 Page Cache 來利用內(nèi)存提高 I/O 效率 采用了零拷貝技術 Producer 生產(chǎn)的數(shù)據(jù)持久化到 broker,采用 mmap 文件映射,實現(xiàn)順序的快速寫入 Customer 從 broker 讀取數(shù)據(jù),采用 sendfile,將磁盤文件讀到 OS 內(nèi)核緩沖區(qū)后,轉(zhuǎn)到 NIO buffer進行網(wǎng)絡發(fā)送,減少 CPU 消耗
參考資料
美團——磁盤I/O那些事: https://tech.meituan.com/2017/05/19/about-desk-io.html
[2]Kafka零拷貝: https://zhuanlan.zhihu.com/p/78335525
[3]Linux - Zero-copy(零拷貝): https://cllc.fun/2020/03/18/linux-zero-copy/
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
評論
圖片
表情
