Kafka為啥這么高吞吐

建議先自行學(xué)習(xí) Kafka 的基礎(chǔ)知識(shí)內(nèi)容引镊。

通常我們講 Kafka 是一個(gè)高可靠猴蹂、高吞吐的分布式數(shù)據(jù)流系統(tǒng)退子。本文只討論其高吞吐的特性。思考幾個(gè)問(wèn)題:

  • Kafka 的哪些設(shè)計(jì)促成了其高吞吐的特性
  • 對(duì)比一般的消息隊(duì)列(RabbitMQ等)宫仗,Kafka 怎么做到高吞吐的情況下還能保存大量消息

Partion 模型帶來(lái)的高吞吐

Topic 下的 Partion 概念,可以橫向擴(kuò)展旁仿,部署到多臺(tái)服務(wù)器上藕夫。故此不論網(wǎng)絡(luò) I/O 還是服務(wù)器的本地 I/O 都能擴(kuò)展,特別是針對(duì)消費(fèi)端需要高 CPU 計(jì)算的場(chǎng)景枯冈,通過(guò)增加 Partion 數(shù)量和對(duì)應(yīng) Consumer Group 中 Consumer 的數(shù)量毅贮,來(lái)提升系統(tǒng)的吞吐量。

生產(chǎn)環(huán)節(jié):

image

消費(fèi)環(huán)節(jié):

image

配合下面的機(jī)制尘奏,Partion 可以說(shuō)是 Kafka 并行起來(lái)的基礎(chǔ)滩褥。Partion 內(nèi)部是由 Segment 文件組成的,這點(diǎn)和 Elasticsearch 相似炫加。

Broker 層面

磁盤順序讀寫(xiě)

一般印象中瑰煎,內(nèi)存讀寫(xiě)肯定比磁盤讀寫(xiě)快铺然。事實(shí)上磁盤可能比人們預(yù)想的更慢、或者更快酒甸,取決于怎么使用它魄健。一個(gè)良好設(shè)計(jì)的磁盤結(jié)構(gòu)通常和我們的網(wǎng)絡(luò) I/O 一樣快。

磁盤的模型圖:

image

說(shuō)起磁盤慢的主要原因在于其尋道操作插勤,在于磁盤的磁頭在盤面上的物理位移沽瘦。我們來(lái)看磁盤調(diào)度算法里面經(jīng)典的 SCAN 算法(又稱電梯算法)如下圖所示:

image

例如,磁盤請(qǐng)求隊(duì)列中的請(qǐng)求順序分別為 55饮六、58其垄、39、18卤橄、90绿满、160、150窟扑、38喇颁、184,磁頭初始位置是 100 磁道嚎货。釆用 SCAN 算法時(shí)橘霎,不但要知道磁頭的當(dāng)前位置,還要知道磁頭的移動(dòng)方向殖属,假設(shè)磁頭沿磁道號(hào)增大的順序移動(dòng)姐叁,則磁頭的運(yùn)動(dòng)過(guò)程如上圖所示。磁頭共移動(dòng)了( 50+10+24+94+32+3+16+1+20 ) = 250 個(gè)磁道洗显,平均尋找長(zhǎng)度 = 250/9 = 27.8外潜。那么對(duì)于我們最先想要訪問(wèn)的 55 號(hào)位置,要等到磁頭第六次真實(shí)位移后才能訪問(wèn)到挠唆。

如此可見(jiàn)順序讀寫(xiě)對(duì)磁盤性能的重要性处窥。如果我們只進(jìn)行順序讀寫(xiě),則能極大提高讀寫(xiě)效率玄组,甚至能高于內(nèi)存的隨機(jī)訪問(wèn)滔驾。更多的速度對(duì)比在文章《ACM Queue article》中,結(jié)論如圖:

image

故此俄讹,Producer 生產(chǎn)消息是不斷追加到磁盤文件的哆致,Consumer 消費(fèi)消息也是從磁盤順序讀取的,都充分利用到了磁盤的順序讀寫(xiě)性能患膛。

利用Page Cache

Kafka 利用到了現(xiàn)代操作系統(tǒng)的特性沽瞭,Page Cache。Page Cache 是通過(guò)將磁盤中的數(shù)據(jù)緩存到內(nèi)存中,從而減少磁盤 I/O 操作驹溃,從而提高性能城丧。此外,還要確保在 Page Cache 中的數(shù)據(jù)更改時(shí)能夠被同步到磁盤上豌鹤,后者被稱為 page 回寫(xiě)(page writeback)亡哄。

當(dāng)上層有寫(xiě)操作時(shí),操作系統(tǒng)只是將數(shù)據(jù)寫(xiě)入 Page Cache 布疙,同時(shí)標(biāo)記 Page 屬性為 Dirty蚊惯。當(dāng)讀操作發(fā)生時(shí),先從 Page Cache 中查找灵临,如果發(fā)生缺頁(yè)才進(jìn)行磁盤調(diào)度截型,最終返回需要的數(shù)據(jù)。實(shí)際上 Page Cache 是把盡可能多的空閑內(nèi)存都當(dāng)做了磁盤緩存來(lái)使用儒溉。同時(shí)如果有其他進(jìn)程申請(qǐng)內(nèi)存宦焦,回收 Page Cache 的代價(jià)又很小,所以現(xiàn)代的 OS 都支持 Page Cache顿涣。

相比于應(yīng)用程序自己(Kafka 是 Java 程序)做 cache波闹, 使用 Page Cache 有如下優(yōu)勢(shì):

  1. 操作系統(tǒng)會(huì)自行將連續(xù)的小量寫(xiě)操作批量處理為物理寫(xiě)操作,從而提高 IO 吞吐涛碑。
  2. 操作系統(tǒng)會(huì)盡量將寫(xiě)操作重新排序以減小寫(xiě)磁盤時(shí)的磁頭偏移量精堕,從而提高 IO 吞吐。
  3. 所有空閑內(nèi)存都自動(dòng)構(gòu)成 Page Cache蒲障。
  4. 如果在應(yīng)用程序 Heap 內(nèi)管理緩存歹篓,JVM 的 GC 線程會(huì)頻繁掃描 Heap 空間,帶來(lái)不必要的開(kāi)銷揉阎。如果 Heap 過(guò)大庄撮,執(zhí)行一次 Full GC 對(duì)系統(tǒng)的可用性來(lái)說(shuō)將是極大的挑戰(zhàn)。
  5. 所有在 JVM 內(nèi)的對(duì)象都不免帶有一個(gè) Object Overhead(千萬(wàn)不可小視)余黎,內(nèi)存的有效空間利用率會(huì)因此降低重窟。
  6. 所有的 In-Process Cache 在OS中都有一份同樣的 PageCache载萌。所以通過(guò)只在PageCache 中做緩存至少可以提高一倍的緩存空間惧财。
  7. 如果 Kafka 重啟,所有的 In-Process Cache都會(huì)失效扭仁,而 OS 管理的 PageCache 依然可以繼續(xù)使用垮衷。

底層 zero-copy 技術(shù)帶來(lái)的高吞吐

首先來(lái)看一下傳統(tǒng)的通過(guò)網(wǎng)絡(luò)讀取文件涉及到的傳輸過(guò)程:

image

涉及到四次內(nèi)存拷貝過(guò)程:

  1. DMA data from disk to read buffer

  2. Copy data from read buffer to application buffer

  3. Copy data from application buffer to socket buffer

  4. DMA buffer from socket buffer to network

注:read buffer 為 page cache,socket buffer 為內(nèi)核 socket buffer乖坠。

并涉及到四次上下文切換:

image

看上去現(xiàn)代操作系統(tǒng)怎么這么蠢搀突?實(shí)際上當(dāng)初設(shè)計(jì)這一套機(jī)制是為了提高性能,利用操作系統(tǒng)內(nèi)部 kernel buffer:

  • read 操作可以利用readahead cache機(jī)制熊泵,提前為應(yīng)用程序準(zhǔn)備好數(shù)據(jù)仰迁,當(dāng)應(yīng)用程序所需的數(shù)據(jù)量小于 kernel buffer 時(shí)可以顯著地提升性能
  • write 操作可以異步執(zhí)行

但實(shí)際上 Kafka 的場(chǎng)景是要實(shí)現(xiàn)高吞吐的文件數(shù)據(jù)傳輸甸昏,這種機(jī)制就成為了系統(tǒng)瓶頸。

利用 zero-copy 技術(shù)

上訴內(nèi)存拷貝的步驟 2 和 3 看起來(lái)都是浪費(fèi)徐许,因?yàn)閼?yīng)用程序并沒(méi)有對(duì)數(shù)據(jù)進(jìn)行過(guò)加工施蜜。實(shí)際上,數(shù)據(jù)可以直接從 read buffer 傳輸?shù)?socket buffer雌隅。在 Linux 系統(tǒng)里面的系統(tǒng)調(diào)用 sendfile() 對(duì)此進(jìn)行了支持翻默。

image

涉及到三次內(nèi)存拷貝過(guò)程:

  1. DMA data from disk to read buffer

  2. Copy data from read buffer to socket buffer

  3. DMA buffer from socket buffer to network

并且使得上線文切換減少到兩次:

image

但這還不是 zero-copy,CPU 依然參與了一次內(nèi)存拷貝恰起。在網(wǎng)卡支持gather operations特性并且 Linux 2.4 之后修械,可以進(jìn)一步優(yōu)化為:

image

涉及到兩次內(nèi)存拷貝過(guò)程:

  1. DMA data from disk to read buffer

  2. No data copied to socket buffer, only the descriptors with information about the location and length

  3. DMA buffer from read buffer to network

優(yōu)勢(shì)和劣勢(shì)

為了使用 zero-copy,很明顯的一點(diǎn)劣勢(shì)就是應(yīng)用程序即 Kafka 的 Broker 不能對(duì)數(shù)據(jù)進(jìn)行二次加工检盼,數(shù)據(jù)進(jìn)來(lái)是什么樣子出去就是什么樣子肯污。與此同時(shí)的優(yōu)勢(shì)就是,Producer 到 Consumer 可以做端到端的壓縮梯皿,反正中間的 Broker 不能修改數(shù)據(jù)本身仇箱。實(shí)際上這種端到端的壓縮也是構(gòu)成高吞吐的原因之一。

綜合一下 PageCahce 和 zero-copy

熱數(shù)據(jù)就直接讀 PageCahce东羹,冷數(shù)據(jù)就走 zero-copy剂桥,性能都很好,完美属提!

Producer 層面

批量化處理

為了避免「small I/O」帶來(lái)的性能損失权逗,Kafka 提出了message set的概念來(lái)批量化處理消息。這個(gè)簡(jiǎn)單的優(yōu)化帶來(lái)了巨大的性能提升冤议,因?yàn)榕炕幚韼?lái)了更大的網(wǎng)絡(luò)報(bào)文斟薇、更大的順序磁盤操作、更大的連續(xù)內(nèi)存空間恕酸,由此 Kafka 將「突發(fā)式的隨機(jī)消息」轉(zhuǎn)變?yōu)轫樞虻南⒘魈峁┙o下游的 Consumer堪滨。

批量化處理使得 Producer 的發(fā)送變成了異步,那么為了保證消息的可靠性蕊温,Kafka 提供了 ack 的機(jī)制:

  • 0:這意味著 Producer 無(wú)需等待來(lái)自 Broker 的確認(rèn)而繼續(xù)發(fā)送下一批消息袱箱。這種情況下數(shù)據(jù)傳輸效率最高,但是數(shù)據(jù)可靠性確是最低的义矛。
  • 1(默認(rèn)):這意味著 Producer 在 ISR 中的 leader 已成功收到的數(shù)據(jù)并得到確認(rèn)后發(fā)送下一條消息发笔。如果 leader宕機(jī)了 ,則會(huì)丟失數(shù)據(jù)凉翻。
  • -1(或者是all): Producer 需要等待 ISR 中的所有 follower 都確認(rèn)接收到數(shù)據(jù)后才算一次發(fā)送完成了讨,可靠性最高。

數(shù)據(jù)壓縮

Kafka 支持?jǐn)?shù)據(jù)端到端的壓縮,Producer 可以通過(guò) GZIP 或 Snappy 格式對(duì)消息集合進(jìn)行壓縮前计,以減輕網(wǎng)絡(luò)傳輸量和磁盤數(shù)據(jù)量胞谭。Producer 壓縮之后,在 Consumer 需進(jìn)行解壓男杈,雖然增加了 CPU 的工作韭赘,但在對(duì)大數(shù)據(jù)處理上,瓶頸在網(wǎng)絡(luò)上而不是 CPU 势就,所以這個(gè)成本很值得泉瞻。

Consumer 層面

pull 模型

到底是用 push 模型還是 pull 模型,不同的系統(tǒng)有不同的選擇苞冯。Kafka 使用的 pull 模型袖牙,這樣有助于 Consumer 自行控制消費(fèi)速度,不會(huì)產(chǎn)生消息積壓到 Consumer 的情形舅锄。

另一個(gè)好處是鞭达,Consumer 可以根據(jù)自身的情況,選擇是否批量去 Broker 拉取消息皇忿,以增加整體的吞吐畴蹭。這在 push 模型里就很難辦,因?yàn)?Broker 很難知道 Consumer 的負(fù)載情況從而不知道是否應(yīng)該批量推送鳍烁。

針對(duì)傳統(tǒng) pull 模型的一個(gè)劣勢(shì)叨襟,即如果 Broker 那里沒(méi)有消息 Consumer 會(huì)一直不斷嘗試獲取,Kafka 這里使用了「long polling」長(zhǎng)輪詢機(jī)制幔荒。Consumer 在發(fā)起一次請(qǐng)求后立即掛起糊闽,一直到 Broker 有更新的時(shí)候,Broker 才會(huì)主動(dòng)推送信息到 Consumer爹梁。 在 Broker 有更新并推送信息過(guò)來(lái)之前這個(gè)周期內(nèi)右犹,Consumer 不會(huì)有新的多余的請(qǐng)求發(fā)生,Broker 對(duì)此 Consumer 也啥都不用干姚垃,只保留最基本的連接信息念链,一旦 Broker 有更新將推送給 Consumer,Consumer 將相應(yīng)的做出處理积糯,處理完后再重新發(fā)起下一輪請(qǐng)求掂墓。

消息確認(rèn)機(jī)制

以往的消息隊(duì)列為了記錄一條消息是否被消費(fèi)掉,在其 broker 層做了很多工作:

  1. 記錄每條消息的狀態(tài)絮宁,是否發(fā)送梆暮、是否確認(rèn)等
  2. 和 consumer 確認(rèn)之間的 ACK 機(jī)制
  3. 異常邏輯的處理服协,比如消息發(fā)送了之后一直沒(méi)有 ACK 確認(rèn)要怎么處理

相比之下 Kafka 使用了簡(jiǎn)單的 offset 機(jī)制绍昂,摒棄了對(duì)消息的狀態(tài)轉(zhuǎn)換。因?yàn)槊總€(gè) Partition 都只有一個(gè) Consumer 在消費(fèi),故每個(gè) Consumer 都只需要記錄其本身的消費(fèi)偏移量 offset窘游,簡(jiǎn)單有效唠椭。老版本的 offset 保存在 zookeeper 中,后面改為存放在一個(gè)特殊的 Topic 中忍饰。

使用 offset 的另一個(gè)好處是 Consumer 可以重復(fù)去消費(fèi)贪嫂,以適配某些場(chǎng)景。

參考

原文載于Kafka為啥這么高吞吐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末艾蓝,一起剝皮案震驚了整個(gè)濱河市力崇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赢织,老刑警劉巖亮靴,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異于置,居然都是意外死亡茧吊,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門八毯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)搓侄,“玉大人,你說(shuō)我怎么就攤上這事话速⊙茸伲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵泊交,是天一觀的道長(zhǎng)俊柔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)活合,這世上最難降的妖魔是什么雏婶? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮白指,結(jié)果婚禮上留晚,老公的妹妹穿的比我還像新娘。我一直安慰自己告嘲,他們只是感情好错维,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著橄唬,像睡著了一般赋焕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仰楚,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天隆判,我揣著相機(jī)與錄音犬庇,去河邊找鬼。 笑死侨嘀,一個(gè)胖子當(dāng)著我的面吹牛臭挽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咬腕,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼欢峰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了涨共?” 一聲冷哼從身側(cè)響起纽帖,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎举反,沒(méi)想到半個(gè)月后抛计,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡照筑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年吹截,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凝危。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡波俄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛾默,到底是詐尸還是另有隱情懦铺,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布支鸡,位于F島的核電站冬念,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏牧挣。R本人自食惡果不足惜急前,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瀑构。 院中可真熱鬧裆针,春花似錦、人聲如沸寺晌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)呻征。三九已至耘婚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間陆赋,已是汗流浹背沐祷。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工嚷闭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人戈轿。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像阵子,于是被迫代替她去往敵國(guó)和親思杯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容