kafka 為什麼能那麼快?高效讀寫資料,原來是這樣做到的
1. 利用 Partition 實現並行處理
我們都知道 Kafka 是一個 Pub-Sub 的訊息系統,無論是釋出還是訂閱,都要指定 Topic。
Topic 只是一個邏輯的概念。每個 Topic 都包含一個或多個 Partition,不同 Partition 可位於不同節點。
一方面,由於不同 Partition 可位於不同機器,因此可以充分利用叢集優勢,實現機器間的並行處理。另一方面,由於 Partition 在物理上對應一個資料夾,即使多個 Partition 位於同一個節點,也可通過配置讓同一節點上的不同 Partition 置於不同的磁碟上,從而實現磁碟間的並行處理,充分發揮多磁碟的優勢。
能並行處理,速度肯定會有提升,多個工人肯定比一個工人乾的快。
2. 順序寫磁碟
Kafka 中每個分割槽是一個有序的,不可變的訊息序列,新的訊息不斷追加到 partition 的末尾,這個就是順序寫。
很久很久以前就有人做過基準測試:《每秒寫入2百萬(在三臺廉價機器上)》
由於磁碟有限,不可能儲存所有資料,實際上作為訊息系統 Kafka 也沒必要儲存所有資料,需要刪除舊的資料。又由於順序寫入的原因,所以 Kafka 採用各種刪除策略刪除資料的時候,並非通過使用“讀 - 寫”模式去修改檔案,而是將 Partition 分為多個 Segment,每個 Segment 對應一個物理檔案,通過刪除整個檔案的方式去刪除 Partition 內的資料。這種方式清除舊資料的方式,也避免了對檔案的隨機寫操作。
3、零拷貝技術
Kafka 中存在大量的網路資料持久化到磁碟(Producer 到 Broker)和磁碟檔案通過網路傳送(Broker 到 Consumer)的過程。這一過程的效能直接影響 Kafka 的整體吞吐量。
作業系統的核心是核心,獨立於普通的應用程式,可以訪問受保護的記憶體空間,也有訪問底層硬體裝置的許可權。
為了避免使用者程序直接操作核心,保證核心安全,作業系統將虛擬記憶體劃分為兩部分,一部分是核心空間(Kernel-space),一部分是使用者空間(User-space)。
傳統的 Linux 系統中,標準的 I/O 介面(例如read,write)都是基於資料拷貝操作的,即 I/O 操作會導致資料在核心地址空間的緩衝區和使用者地址空間的緩衝區之間進行拷貝,所以標準 I/O 也被稱作快取 I/O。這樣做的好處是,如果所請求的資料已經存放在核心的高速緩衝儲存器中,那麼就可以減少實際的 I/O 操作,但壞處就是資料拷貝的過程,會導致 CPU 開銷。
我們把 Kafka 的生產和消費簡化成如下兩個過程來看[2]:
網路資料持久化到磁碟 (Producer 到 Broker)
磁碟檔案通過網路傳送(Broker 到 Consumer)
總結
如果,面試官再問我:Kafka為什麼這麼快?我會這麼說:
partition 並行處理
順序寫磁碟,充分利用磁碟特性
利用了現代作業系統分頁儲存 Page Cache 來利用記憶體提高 I/O 效率
採用了零拷貝技術
Producer 生產的資料持久化到 broker,採用 mmap 檔案對映,實現順序的快速寫入
Customer 從 broker 讀取資料,採用 sendfile,將磁碟檔案讀到 OS 核心緩衝區後,轉到 NIO buffer進行網路傳送,減少 CPU 消耗