kafka是一個訊息佇列中介軟體,它的高吞吐量其中一個重要功臣就是“零複製”。從字面上理解,意思是資料不需要經過多次複製,系統性能可以大幅度提升。其實,不僅在kafka中,Java NIO,netty,rocketMQ等框架中也都用到了零複製。要了解什麼是零複製,需要從I/O的幾個概念瞭解起。
快取I/O快取I/O又被稱作標準I/O,是大多少檔案系統預設I/O。為了減少讀盤的次數,同時也為了保護系統本身的安全,快取I/O在一定程度上分離了核心空間和使用者空間。但也因此,資料在傳輸過程中需要在使用者空間和核心空間之間進行多次的複製,這些資料複製操作所帶來的CPU以及記憶體開銷是非常大的。
下圖示例列出了一次快取IO讀和寫需要經過的步驟:
快取I/O資料傳輸示意圖
對於快取I/O,一個讀操作有3次資料複製,一次寫操作又會有3次的資料複製。
讀操作:磁碟->核心快取區->使用者空間快取區->應用程式記憶體。
寫操作:應用程式記憶體->使用者空間快取區->Socket快取區->網路。
直接I/O直接IO就是指沒有使用者級的快取區,但是核心快取區還是有的。這樣就減少一次從核心緩衝區到使用者程式快取的資料複製。如下圖所示:
直接I/O資料傳輸示意圖
記憶體對映檔案首先,對映的意思就是建立一種一一對應關係,是指硬碟上檔案的位置與程序邏輯地址的對應關係。這種對應關係純屬是邏輯上的概念,物理上是不存在的。在記憶體對映的過程中,並沒有實際的資料複製,檔案沒有被載入記憶體,只是邏輯上被放入了記憶體,記憶體中實際只是一個邏輯地址。
記憶體對映檔案示意圖
如上圖所示,資料不再經過應用程式記憶體,直接從核心快取區到socket緩衝區。
零複製零複製連核心快取區到socket快取區也省了,底層的網絡卡驅動程式直接讀取核心快取區的資料併發送到網路。在整個過程中,只發生了2次資料複製。一次是從磁碟到核心快取區,另一次是從核心快取區到網路。既然有發生資料複製,為什麼還叫“零複製”,那是因為所說的零複製是指資料在記憶體中沒有發生資料複製。
零複製