Kafka 中所謂的 ‘零拷貝’ 技術到底是什么?


文章收錄地址: Java-Bang 專注於系統架構、高可用、高性能、高並發類技術分享

除了消息順序追加、頁緩存等技術,Kafka 還使用零拷貝技術來進一步提升性能。所謂的零拷貝是指將數據直接從磁盤文件復制到網卡設備中,而不需要經由應用程序之手。零拷貝大大提高了應用程序的性能,減少了內核和用戶模式之間的上下文切換。對 Linux 操作系統而言,零拷貝技術依賴於底層的 sendfile() 方法實現。對應於 Java 語言,FileChannal.transferTo() 方法的底層實現就是 sendfile() 方法。

單純從概念上理解“零拷貝”比較抽象,這里簡單地介紹一下它。考慮這樣一種常用的情形:你需要將靜態內容(類似圖片、文件)展示給用戶。這個情形就意味着需要先將靜態內容從磁盤中復制出來放到一個內存 buf 中,然后將這個 buf 通過套接字(Socket)傳輸給用戶,進而用戶獲得靜態內容。這看起來再正常不過了,但實際上這是很低效的流程,我們把上面的這種情形抽象成下面的過程:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

首先調用 read() 將靜態內容(這里假設為文件 A )讀取到 tmp_buf,然后調用 write() 將 tmp_buf 寫入 Socket,如下圖所示

在這個過程中,文件 A 經歷了4次復制的過程:

  1. 調用 read() 時,文件 A 中的內容被復制到了內核模式下的 Read Buffer 中。
  2. CPU 控制將內核模式數據復制到用戶模式下。
  3. 調用 write() 時,將用戶模式下的內容復制到內核模式下的 Socket Buffer 中。
  4. 將內核模式下的 Socket Buffer 的數據復制到網卡設備中傳送。

從上面的過程可以看出,數據平白無故地從內核模式到用戶模式“走了一圈”,浪費了2次復制過程:第一次是從內核模式復制到用戶模式;第二次是從用戶模式再復制回內核模式,即上面4次過程中的第2步和第3步。而且在上面的過程中,內核和用戶模式的上下文的切換也是4次。

如果采用了零拷貝技術,那么應用程序可以直接請求內核把磁盤中的數據傳輸給 Socket,如下圖所示。

零拷貝技術通過 DMA(Direct Memory Access)技術將文件內容復制到內核模式下的 Read Buffer 中。不過沒有數據被復制到 Socket Buffer,相反只有包含數據的位置和長度的信息的文件描述符被加到 Socket Buffer 中。DMA 引擎直接將數據從內核模式中傳遞到網卡設備(協議引擎)。這里數據只經歷了2次復制就從磁盤中傳送出去了,並且上下文切換也變成了2次。零拷貝是針對內核模式而言的,數據在內核模式下實現了零拷貝。

要掌握Kafka的核心實現原理,不僅僅只是Kafka的日志格式、日志索引、日志清理等方面的內容,也包含底層物理存儲相關的知識點。這樣才能對 Kafka 的整理實現脈絡有比較清晰的認知。加油吧~打工人!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM