Kafka為什么會這么快
在系統(tǒng)設(shè)計中,會用到消息中間件來做服務(wù)異步化,系統(tǒng)解耦,或者是做流量削峰,常用的消息中間件有rabbitMq,activeMq以及阿里的RocketMq等等,都各自有各自的優(yōu)勢,但是就吞吐量來說,kafka是其中的佼佼者。在單機情況下,網(wǎng)友做的對比如下:

性能對比
為什么kafka會這么快呢?
發(fā)布訂閱模式
一個普通的發(fā)布訂閱模型如下圖所示:

發(fā)布訂閱模式
以kafka為例,生產(chǎn)者產(chǎn)生消息,并將消息Push到kafka集群,消費者主動去kafka集群Pull數(shù)據(jù)。這種模型有個好處,消費的速率完全由消費者控制,kafka集群類似于一個蓄水池,避免因生產(chǎn)者產(chǎn)生消息過快消費者來不及消費而導(dǎo)致消費者被壓垮的現(xiàn)象。
kafka為什么快要從兩方面分析,生產(chǎn)者產(chǎn)生的消息寫入集群時快和消費者消費消息時從集群讀取快。
寫入快
寫入快主要是兩方面原因:順序?qū)懭牒蚆MFile。
順序?qū)懭?/strong>
kafka將消息存儲在硬盤,通常認為硬盤的讀寫是比較慢,但是為什么kafka快呢?平時所說的磁盤讀寫慢是指隨機讀寫比較慢,因為磁盤每次隨機讀寫都要物理尋址,這是非常耗時的操作,順序讀寫的速度還是比較快的。如下圖所示:

順序?qū)懭?/center>
kafka每次收到新的消息之后都會將消息存儲在尾部,按照順序存儲消息。但是消息一旦存儲無法刪除。
當消費者消費時也是順序消費,每個消費者會有一個偏移量,記錄當前消費的消息的位置。如下圖所示:

順序消費
MMFile
MMFile是指Memory Mapped Files,即內(nèi)存映射技術(shù)。操作系統(tǒng)為了解決內(nèi)存和硬盤讀寫速度之間的差異,采用了內(nèi)存映射技術(shù),內(nèi)存被劃分為若干頁,每一頁被映射到一塊磁盤空間,因為內(nèi)存是遠遠小于磁盤空間的,所以分頁經(jīng)常會按照一定的算法加載到內(nèi)存,例如先進先出(FIFO),最近最少使用(LRU)等。內(nèi)存中分頁和磁盤空間對應(yīng),操作系統(tǒng)會在合適的時候?qū)?nèi)存分頁中的數(shù)據(jù)定時刷磁盤中去。這種方式為什么可以提高寫入效率呢?通常CPU執(zhí)行過程中為了安全分為內(nèi)核態(tài)和用戶態(tài)。只有內(nèi)核態(tài)才能操作iO設(shè)備,內(nèi)存空間分為內(nèi)核空間和用戶空間。通常內(nèi)存中的數(shù)據(jù)寫入到磁盤要以下幾步:

write操作
數(shù)據(jù)會先從用戶空間拷貝到內(nèi)核空間,然后再由內(nèi)核空間寫入IO設(shè)備。而MMFile則省去了一次用數(shù)據(jù)從戶空間到內(nèi)核空間復(fù)制的開銷。
讀取快
讀取快主要是因為零拷貝(Zero Copy)技術(shù)。上面介紹到數(shù)據(jù)從內(nèi)存空間寫入磁盤的步驟,那么從磁盤讀取數(shù)據(jù)剛好相反,具體過程如下:

read操作
數(shù)據(jù)先從磁盤讀取到內(nèi)核空間,然后再從內(nèi)核空間復(fù)制到用戶空間,然后再到Socket,最后傳輸?shù)较M者。
Linux提供了一種sendFile系統(tǒng)調(diào)用,可以將數(shù)據(jù)直接由磁盤拷貝到內(nèi)核空間。省去了一次數(shù)據(jù)從用戶空間到內(nèi)核空間的復(fù)制。這就是所謂的零拷貝技術(shù)。
上面從讀寫兩個角度分析了為什么kafka吞吐量高,其實還有一個重要的原因。
批量數(shù)據(jù)壓縮
kafka不會對每個消息都做壓縮,而是對一批消息壓縮,然后將數(shù)據(jù)統(tǒng)一發(fā)送。將所有的消息變?yōu)橐粋€批量文件,然后直接丟給消費者。
綜上所述,kafka通過MMFile技術(shù)快速將數(shù)據(jù)順序?qū)懭氪疟P,在讀取時通過零拷貝技術(shù)快速讀取,然后通過批量數(shù)據(jù)壓縮將數(shù)據(jù)傳輸?shù)较M者。這就是kafka快的秘訣。然而魚與熊掌不可兼得,速度和可靠性不可能同時滿足,需要根據(jù)實際業(yè)務(wù)情況在二者之間作出取舍。例如當用kafka做日志聚合和網(wǎng)站用戶行為分析時速度要比可靠性重要,而在某些消息不允許丟失的場景,可靠性可能是首選。