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






