kafka快速的原因

kafka是大數(shù)據(jù)領(lǐng)域無(wú)處不在的消息中間件,目前廣泛使用的企業(yè)內(nèi)部的實(shí)時(shí)數(shù)據(jù)管道,并幫助企業(yè)構(gòu)建自己的流計(jì)算應(yīng)用程序。
kafka雖然是基于磁盤做的數(shù)據(jù)存儲(chǔ),但卻具有高性能、高吞吐、低延時(shí)的特點(diǎn),器吞吐量動(dòng)輒幾萬(wàn),幾十上百萬(wàn),這其中的原由值得我們一探究竟。
1、順序讀寫
磁盤順序讀寫性能要高于內(nèi)存的隨機(jī)讀寫
眾所周知kafka是將消息記錄持久化到本地磁盤中的,一般人會(huì)認(rèn)為磁盤讀寫性能差,可能會(huì)對(duì)kafka性能如何保證提出質(zhì)疑。實(shí)際上不管是內(nèi)存還是磁盤,快或慢關(guān)鍵在于尋址的方式,磁盤分為順序讀寫與隨機(jī)讀寫,內(nèi)存也一樣分為順序讀寫與隨機(jī)讀寫?;诖疟P的隨機(jī)讀寫確實(shí)很慢,但磁盤的順序讀寫性能卻很高,一般而言要高出磁盤隨機(jī)讀寫三個(gè)數(shù)量級(jí),一些情況下磁盤順序讀寫性能甚至要高于內(nèi)存隨機(jī)讀寫。
磁盤的順序讀寫是磁盤使用模式中最有規(guī)律的,并且操作系統(tǒng)也對(duì)這種模式做了大量?jī)?yōu)化,kafka就是使用了磁盤順序讀寫來(lái)提升的性能。kafka的message是不斷追加到本地磁盤文件末尾的,而不是隨機(jī)的寫入,這使得kafka寫入吞吐量得到了顯著提升
2、page cache
為了優(yōu)化讀寫性能,kafka利用了操作系統(tǒng)本身的page cache,就是利用操作系統(tǒng)自身的內(nèi)存而不是JVM空間內(nèi)存。這樣做的好處有:
(1)避免object消耗:如果是使用java堆,java對(duì)象的內(nèi)存消耗比較大,通常是所存儲(chǔ)數(shù)據(jù)的兩倍甚至更多。
(2)避免GC問(wèn)題:隨著JVm數(shù)據(jù)不斷增多,垃圾回收將會(huì)變得復(fù)雜與緩慢,使用系統(tǒng)緩存就不會(huì)存在GC問(wèn)題。
3、零拷貝(sendfile)
零拷貝并不是不需要拷貝,而是減少不必要的拷貝次數(shù)。通常是說(shuō)在IO讀寫過(guò)程中。
kafka利用linux操作系統(tǒng)“零拷貝(zero-copy)"機(jī)制在消費(fèi)端做的優(yōu)化。
首先來(lái)了解下數(shù)據(jù)從文件發(fā)送到socket網(wǎng)絡(luò)連接中的常規(guī)傳輸路徑
比如:讀取文件,再用socket發(fā)送出去
傳統(tǒng)方式實(shí)現(xiàn):
先讀取、再發(fā)送,實(shí)際經(jīng)過(guò)1~4四次copy。
buffer=File.read
Socket.send(buffer)
*第一步:操作系統(tǒng)從磁盤讀取數(shù)據(jù)到內(nèi)核空間(kernel space)的Page Cache緩沖區(qū)
*第二步;應(yīng)用程序讀取內(nèi)核緩沖區(qū)的數(shù)據(jù)copy到用戶空間(user space)的緩沖區(qū)
*第三步:應(yīng)用程序?qū)⒂脩艨臻g緩沖區(qū)的數(shù)據(jù)copy回內(nèi)核空間到socket緩沖區(qū)
*第四步:操作系統(tǒng)將數(shù)據(jù)從socket緩沖區(qū)copy到網(wǎng)卡,由網(wǎng)卡進(jìn)行網(wǎng)絡(luò)傳輸

傳統(tǒng)方式,讀取磁盤文件并進(jìn)行網(wǎng)絡(luò)發(fā)送,經(jīng)過(guò)的四次數(shù)據(jù)copy是非常繁瑣的。實(shí)際IO讀寫,需要進(jìn)行IO中斷,需要CPU響應(yīng)中斷(帶來(lái)上下文切換),盡管后來(lái)引入DMA來(lái)接管CPU的中斷請(qǐng)求,但四次copy是存在“不必要的拷貝”的。
重新思考傳統(tǒng)IO方式,會(huì)注意到實(shí)際上并不需要第二個(gè)和第三個(gè)數(shù)據(jù)副本。應(yīng)用程序除了緩存數(shù)據(jù)并將其傳輸回套接字緩沖區(qū)之外什么都不做。相反,數(shù)據(jù)可以直接從讀緩沖區(qū)傳輸?shù)教捉幼志彌_區(qū)。
顯然,第二次和第三次數(shù)據(jù)copy其實(shí)在這種場(chǎng)景下沒(méi)有什么幫助反而帶來(lái)開銷,這也正是零拷貝出現(xiàn)的意義。
這種場(chǎng)景:是指讀取磁盤文件后,不需要做其他處理,直接用網(wǎng)絡(luò)發(fā)送出去。試想,如果讀取磁盤的數(shù)據(jù)需要用程序進(jìn)一步處理的話,必須要經(jīng)過(guò)第二次和第三次數(shù)據(jù)copy,讓應(yīng)用程序在內(nèi)存緩沖區(qū)處理。
此時(shí)我們會(huì)發(fā)現(xiàn)用戶態(tài)“空空如也”。數(shù)據(jù)沒(méi)有來(lái)到用戶態(tài),而是直接在核心態(tài)就進(jìn)行了傳輸,但這樣依然還是有多次復(fù)制。首先數(shù)據(jù)被讀取到read buffer中,然后發(fā)到socket buffer,最后才發(fā)到網(wǎng)卡。雖然減少了用戶態(tài)和核心態(tài)的切換,但依然存在多次數(shù)據(jù)復(fù)制。
如果可以進(jìn)一步減少數(shù)據(jù)復(fù)制的次數(shù),甚至沒(méi)有數(shù)據(jù)復(fù)制是不是就會(huì)做到最快呢?
DMA
DMA,全稱叫Direct Memory Access,一種可讓某些硬件子系統(tǒng)去直接訪問(wèn)系統(tǒng)主內(nèi)存,而不用依賴CPU的計(jì)算機(jī)系統(tǒng)的功能。聽著是不是很厲害,跳過(guò)CPU,直接訪問(wèn)主內(nèi)存。傳統(tǒng)的內(nèi)存訪問(wèn)都需要通過(guò)CPU的調(diào)度來(lái)完成。如下圖:

DMS,則可以繞過(guò)CPU,硬件自己去直接訪問(wèn)系統(tǒng)主內(nèi)存。如下圖

回到本文中的文件傳輸,有了DMA后,就可以實(shí)現(xiàn)絕對(duì)的零拷貝,因?yàn)榫W(wǎng)卡是直接去訪問(wèn)系統(tǒng)主內(nèi)存的。如下圖:
總結(jié)
kafka采用順序讀寫、page cache、零拷貝以及分區(qū)分段等這些設(shè)計(jì),再加上在索引方面做的優(yōu)化,另外kafka數(shù)據(jù)讀寫也是批量的而不是單條的,使得kafka就有了高性能、高吞吐、低延時(shí)的特點(diǎn)。這樣kafka提供大容量的磁盤存儲(chǔ)也變成了一種優(yōu)點(diǎn)
java的nio提供了filechannel,它的tarnsferto、transferfrom方法就是zero copy

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容