前言
kafka 作為一個高吞吐量的分布式消息系統,廣泛應用與實時應用場景中。為了實現高效的數據傳輸,kafka使用了零拷貝技術(zero-copy)顯著提高了性能。本文將詳細講解 Kafka 如何利用零拷貝技術優化數據傳輸。
什么是零拷貝
零拷貝技術目的是減少數據傳輸的效率。在傳統的數據傳輸過程中,數據在內核態和用戶態之間進行多次拷貝,而零拷貝技術在內核態直接處理數據傳輸,避免了冗余的拷貝操作。
傳統的傳輸過程,在沒有零拷貝技術的前提下。流程如下:
- 數據從磁盤讀取到內核緩沖區(pageCache)。數據首先從磁盤讀取到內核態的頁面緩存(Page Cache)中。這一步由操作系統負責,通過磁盤驅動程序完成。
- 數據從內核緩沖區復制到用戶緩沖區.應用程序發起讀取請求后,數據從內核態的頁面緩存(Page Cache)復制到用戶態的緩沖區。這一步通常由 read 系統調用完成。
- 數據從用戶緩沖區復制到內核緩沖區進行傳輸。應用程序在準備發送數據時,數據從用戶態的緩沖區再次復制到內核態的網絡緩沖區。這一步通常由 write 系統調用或其他類似的系統調用完成。
- 數據通過網絡發送。內核態的網絡緩沖區中的數據最終通過網絡接口發送到目標機器。
通過這種方式你會發現進行了多次數據復制,占用了大量的CPU和內存資源,那怎么辦呢?
零拷貝技術
為了提高數據傳輸效率,可以采用零拷貝技術,避免數據在用戶態和內核態之間多次拷貝。Linux系統提供了多種零拷貝技術mmap,sendfile和splice等。
sendfile
sendfile 系統調用是一種常見的零拷貝技術,可以在內核態直接將數據從文件描述符傳輸到網絡套接字,而無需在用戶態進行數據拷貝。 sendfile接口定義如下
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
使用sendfile時,數據傳輸過程如下:
1.數據從磁盤讀取到內核緩沖區(Page Cache)
與傳統方法相同,數據從磁盤讀取到內核態的頁面緩存(Page Cache)。
2.數據直接從內核緩沖區發送到網絡
使用 sendfile 系統調用,數據直接從內核態的頁面緩存(Page Cache)傳輸到網絡套接字,避免了從內核態到用戶態的多次拷貝。
sendfile示例代碼如下:
#include <sys/sendfile.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>