Apache Kafka零複製最佳化原理

banq發表於2024-07-04

如果你曾經讀過關於 Kafka 的文章,那麼它所使用的一種特殊最佳化可能會引起你的注意:作業系統的零複製最佳化。

零複製操作就是不對資料進行不必要的複製。

在Kafka中是指作業系統將資料從頁面快取直接複製到套接字緩衝區,實際上完全繞過了 Kafka 代理 Java 程式。

在這之前,Kafka 已經在作業系統的頁面快取中 "保留 "了最新寫入的資料,以便更快地獲取。

這就省去了一些額外的複製和使用者 <-> 核心模式切換。

如果你的應用程式的工作是從磁碟讀取檔案並透過網路傳送,就會產生大量不必要的副本和使用者/核心模式切換。

一些術語:

  • - 讀緩衝區 - 這是作業系統的頁面快取。
  • - 套接字緩衝區 - 這是作業系統管理資料包的位元組緩衝區。
  • - NIC 緩衝區 - 網路卡中的位元組緩衝區。
  • - DMA 複製 - DMA 是直接記憶體訪問(Direct Memory Access)的縮寫,是記憶體控制器的一項功能,允許硬體(圖形卡、音效卡、網路卡等)訪問記憶體(RAM)而無需 CPU 參與。

假設 我們有 4 個模式開關和 4 個資料複製。

  1. 應用程式啟動磁碟 → 作業系統緩衝區 DMA 複製(使用者 → 核心模式)
  2. 讀取緩衝區 → 應用程式緩衝區複製(核心 → 使用者模式)
  3. 應用程式 → 套接字緩衝區複製(使用者模式 → 核心模式)
  4. 套接字緩衝區 → 網路卡緩衝區 DMA 複製(響應寫出後核心 → 使用者模式)

如果需要讀取的資料超過讀取緩衝區的容量,可以迴圈執行步驟 1、2。

在零複製中,這種流程是這樣:
Kafka 以響應請求的二進位制格式儲存資料。

執行最初的第 2 和第 3 步毫無意義,因為 Kafka 不會對給定的資料做任何處理,只會將其傳回核心。

使用零複製後,資料不會複製到 Kafka,而是直接進入 NIC 緩衝區。

 請注意,這裡還有另一項最佳化--讀取緩衝區直接將資料複製到 NIC 緩衝區,而不是套接字緩衝區。

這就是所謂的分散收集操作(又稱向量化 I/O)。

  • - 分散收集scatter-gather:僅在套接字緩衝區中儲存讀緩衝區指標,並讓 DMA 引擎直接從記憶體中讀取這些地址。

最終結果如何?

  • - 2 個使用者/核心模式開關。(少 2 次)
  • - 2 份 DMA 副本(相同)
  • - 1 份很輕量的指標 CPU 副本。(少 2 個)

總結
Kafka使用零複製(Zero-Copy)技術可以有效提升生產力效率。它的原理是:

  1. 將磁碟檔案傳送至核心緩衝區,使用者透過記憶體就能修改核心空間。這樣可以省去使用者到核心空間的資料開銷。
  2. 使用DMA(直接記憶體訪問)技術,網路卡可以直接從核心讀取資料,而不需要先複製到使用者空間緩衝區。
  3. 在Java中,FileChannel的transferTo()方法可以實現零複製。它底層基於作業系統的sendfile系統呼叫,可以將資料從檔案描述符直接複製到套接字緩衝區,而不經過使用者空間。

與傳統的資料傳輸方式相比,Kafka 的零複製技術可以減少 CPU 時脈頻率、減少記憶體複製次數、提高資料傳輸效率。

但是,零複製並非完全沒有資料複製,而是相對於使用者空間而言,需要透過作業系統來複製。這依賴於作業系統和Java NIO的支援來實現。

此外,當啟用SSL/TLS時,Kafka就使用零複製技術了,因為需要對資料進行解密和在大多數Kafka中,CPU很少成為瓶頸,網路頻寬的飽和速度要快得多,所以減少記憶體對網路效能的影響通常不大。

在大多數 Kafka 部署中,零複製的影響並不大,因為CPU 很少是瓶頸。
 

相關文章