字節一面:Kafka為什么這么快?
前言
大家好,我是田螺。
有位粉絲去字節面試。問了一道很經典的八股文:kafka為什么這么快?
其實這不就送分題嘛,哈哈~~ 我梳理了田螺版的答案:
- 批量處理思想
- 磁盤順序讀寫
- 零拷貝技術
- 頁緩存加速消息讀寫
- 分區與并行處理
- 數據壓縮
1.批量處理思想
之前寫SQL優化技巧的時候,就提到批量更新SQL~~
假如你需要搬一萬塊磚到樓頂,你有一個電梯,電梯一次可以放適量的磚(最多放500),你可以選擇一次運送一塊磚,也可以一次運送500,你覺得哪個時間消耗大?
kafka為什么這么快,就是使用了批量操作思想。
Kafka支持批量發送和接收消息。生產者可以將多個消息打包成一個批次發送,消費者也可以一次性獲取多個消息進行處理。這樣可以減少網絡開銷和磁盤I/O次數,提高性能。
- Kafka生產者send()方法看似單條發送,實則內部批量處理。消息先緩存,待數量足夠或某個時間間隔,Kafka客戶端將其打包成批次,一并發送給Broker。。
- Broker服務端Kafka不會將消息分批后逐條處理,因其效率低下。Kafka智能地以批為單位處理消息,整個Broker處理流程(寫入、讀取、復制),批消息均保持原狀不被拆分。
- 消費者從Broker拉取一批消息后,在客戶端拆分這批消息,再逐條交給用戶代碼處理。
2. 磁盤順序讀寫
Kafka大量使用磁盤進行數據存儲,并采用順序寫入的方式。順序寫入磁盤的速度遠遠高于隨機寫入,因為磁盤的物理結構決定了順序寫入可以減少磁頭的尋道時間,從而提高寫入速度。
kafka是如何使用順序讀寫提升磁盤IO性能的?
每個分區接收到的Producer消息,均按順序被寫入對應的日志文件中,當文件寫滿后,則開啟新文件進行后續寫入。在消費環節,從全局指定位置(即特定日志文件的特定偏移處)起,消息被順序讀取。
3. 零拷貝技術
Kafka使用零拷貝技術將數據從磁盤直接發送到網絡,避免了在內核空間和用戶空間之間的多次數據拷貝。
傳統的文件傳輸方式通常需要將數據從磁盤讀取到內核緩沖區,然后再從內核緩沖區拷貝到用戶空間,最后從用戶空間拷貝到網絡緩沖區發送出去。而零拷貝技術可以直接將數據從磁盤的文件描述符傳遞給網絡接口,減少了數據拷貝的次數和開銷。
傳統的IO流程:
圖片
- 用戶應用進程調用read函數,向操作系統發起IO調用,上下文從用戶態轉為內核態(切換1)
- DMA控制器把數據從磁盤中,讀取到內核緩沖區。
- CPU把內核緩沖區數據,拷貝到用戶應用緩沖區,上下文從內核態轉為用戶態(切換2),read函數返回
- 用戶應用進程通過write函數,發起IO調用,上下文從用戶態轉為內核態(切換3)
- CPU將用戶緩沖區中的數據,拷貝到socket緩沖區
- DMA控制器把數據從socket緩沖區,拷貝到網卡設備,上下文從內核態切換回用戶態(切換4),write函數返回
sendfile+DMA scatter/gather實現的零拷貝流程如下:
圖片
- 用戶進程發起sendfile系統調用,上下文(切換1)從用戶態轉向內核態
- DMA控制器,把數據從硬盤中拷貝到內核緩沖區。
- CPU把內核緩沖區中的文件描述符信息(包括內核緩沖區的內存地址和偏移量)發送到socket緩沖區
- DMA控制器根據文件描述符信息,直接把數據從內核緩沖區拷貝到網卡
- 上下文(切換2)從內核態切換回用戶態,sendfile調用返回。
零拷貝的實現方式,大家可以看看我的這篇文章哈:看一遍就理解:零拷貝詳解
Kafka 在處理大規模數據傳輸和存儲時,采用了幾種高效的零拷貝技術,主要包括:
- sendfile:用于減少文件讀取和網絡傳輸中的內存拷貝,提高消息傳輸效率。
- DMA(硬件加速):在高性能硬件環境下,Kafka 可通過硬件支持的 DMA 技術來加速數據傳輸。
4.頁緩存加速消息讀寫
Kafka利用PageCache(操作系統內存中的磁盤文件緩存)來加速消息的讀寫。
當應用程序讀寫文件時,實際上操作的是PageCache中的副本。寫入時,數據先寫入PageCache,再批量寫到磁盤;讀取時,若PageCache中有數據則直接讀取,否則操作系統會從磁盤加載數據到PageCache。Kafka讀寫消息時充分利用這一特性,由于消息通常很快被消費,按LRU策略,PageCache命中率高。這既提高了讀取速度,又為寫入讓出了磁盤IO資源,間接提升了寫入性能。
5. 分區與并行處理
Kafka的主題(Topic)可以被分成多個分區(Partition),每個分區可以分布在不同的服務器上。這樣可以實現并行寫入和讀取,提高了吞吐量。
其實以前寫接口優化的時候,就提到并行優化的方式,思想道理其實是一樣的:
比如一個查詢APP首頁查詢接口:查用戶信息、查banner信息、查彈窗信息是串行的:
圖片
如果修改為并行,接口耗時將大大降低。
圖片
6. 數據壓縮
生產者在發送消息到Kafka集群之前,可以對消息進行壓縮。這種在生產者端進行壓縮的方式能夠減少發送到Kafka集群的數據量,從而降低網絡傳輸的帶寬消耗,并提高數據傳輸的效率。
壓縮傳輸內容,傳輸報文變得更小,因此傳輸會更快啦。10M帶寬,傳輸10k的報文,一般比傳輸1M的會快呀。