為什麼Kafka的速度那麼快

 閱讀大約需要1分鐘

為什麼Kafka的速度那麼快

我們都知道Kafka是基於磁盤進行存儲的,但Kafka官方又稱其具有高性能、高吞吐、低延時的特點,其吞吐量動輒幾十上百萬。

一般認為在磁盤上讀寫數據是會降低性能的,因為尋址會比較消耗時間,那麼Kafka又是怎麼做到其吞吐量動輒幾十上百萬的呢?

kafka的高性能是底層設計、分佈式partition存儲、高效利用磁盤和操作系統特性、批量壓縮等,綜合產生的結果。
一、利用Partition實現並行處理

我們知道Kafka是一個Pub-Sub的消息系統,無論是發布還是訂閱,都要指定Topic,Topic只是一個邏輯的概念。每個Topic都包含一個或多個Partition,不同Partition可位於不同節點。

一方面由於不同Partition可位於不同機器,因此可以充分利用集群優勢,實現機器間的並行處理。

另一方面由於Partition在物理上對應一個文件夾,即使多個Partition位於同一個節點,也可通過配置讓同一節點上的不同Partition置於不同的磁盤上,從而實現磁盤間的並行處理,充分發揮多磁盤的優勢。

二、順序寫磁盤

由於存儲介質的特性,磁盤本身存取就比主存慢,再加上機械運動耗費,磁盤的存取速度往往是主存的幾百分之一甚至幾千分之一,怎麼樣才能提高磁盤的讀寫效率呢?

有以下兩種方法:

    1. 預讀或者提前讀;
    1. 合併寫——多個邏輯上的寫操作合併成一個大的物理寫操作中; 即採用磁盤順序讀寫(不需要尋道時間,只需很少的旋轉時間)。 僅僅將數據追加到文件的末尾,不是在文件的隨機位置來修改數據。 Kafka中每個分區是一個有序的,不可變的消息序列,新的消息不斷追加到partition的末尾,這個就是順序寫。
三、利用page cache+mmap

即便是順序寫入磁盤,磁盤的訪問速度還是不可能追上內存。所以Kafka的數據並不是實時的寫入硬盤,它充分利用了現代操作系統分頁存儲來利用內存提高I/O效率。

page cache(os cache):【操作系統自己管理的緩存】以Page為單位,緩存文件內容。

mmap即Memory Mapped Files內存文件映射,mmap其實就是把物理上的磁盤文件的一些地址和page cache地址進行一層映射,使得進程像讀寫磁盤一樣讀寫內存,定時有os幫助我們將數據刷寫到磁盤

Kafka在寫入磁盤文件的時候,可以直接寫入這個os cache裡,也就是僅僅寫入內存中, 接下來由操作系統自己決定什麼時候把os cache裡的數據真的刷入磁盤文件中。通過這一個步驟, 就可以將磁盤文件寫性能提升很多了,因為其實這里相當於是在寫內存,不是在寫磁盤。

四、零拷貝

Kafka在讀取磁盤時做了哪些優化?

  • 基於sendfile實現zero copy

Linux2.4+ 內核通過sendfile系統調用提供了零拷貝。數據通過DMA拷貝到內核態Buffer後,直接通過DMA拷貝到NIO Buffer,無需CPU拷貝。 這也是零拷貝這一說法的來源。除了減少數據拷貝外,因為整個讀文件的網絡發送由一個sendfile調用完成,整個過程只有兩次上下文切換,因此大大提高了性能。

Kafka在這裡採用的方案是通過NIO的transferTo/transferFrom調用操作系統的sendfile實現零拷貝, 總共發生2次內核數據拷貝,2次上下文切換和一次系統調用,消除了CPU數據拷貝。

五、批量處理

在很多情況下,系統的瓶頸不是CPU或磁盤,而是網絡IO。因此除了操作系統提供的低級批處理之外,Kafka的客戶端和broker還會在通過網絡發送數據之前, 在一個批處理中累積多條記錄 (包括讀和寫)。記錄的批處理分攤了網絡往返的開銷,使用了更大的數據包從而提高了帶寬利用率。

六、數據壓縮

Producer可將數據壓縮後發送給broker,從而減少網絡傳輸代價,目前支持的壓縮算法有:snappy、gzip、lz4、zstd。數據壓縮一般都是和批處理配套使用來作為優化手段的。

總結為什麼kafka速度那麼快:

  • partition並行處理
  • 順序寫磁盤,充分利用磁盤特性
  • 利用了現代操作系統分頁存儲Page Cache來利用內存提高I/O效率
  • 採用了零拷貝技術
  • producer生產的數據持久化到broker,採用mmap文件映射,實現順序的快速寫入
  • customer從broker讀取數據,採用sendfile系統調用,將磁盤文件讀到OS內核緩衝區後,轉到 NIO buffer進行網絡發送,減少CPU消耗
  • 把所有的消息都變成一個批量的文件,並且進行合理的批量壓縮,減少網絡IO損耗。