Kafka 是怎么存儲的狰域?為什么速度那么快炕淮?

文章收錄地址:Java-Bang
專注于系統(tǒng)架構媳荒、高可用尊蚁、高性能、高并發(fā)類技術分享

Kafka 依賴于文件系統(tǒng)(更底層地來說就是磁盤)來存儲和緩存消息吃嘿。在我們的印象中祠乃,對于各個存儲介質(zhì)的速度認知大體同下圖所示的相同,層級越高代表速度越快兑燥。很顯然亮瓷,磁盤處于一個比較尷尬的位置,這不禁讓我們懷疑 Kafka 采用這種持久化形式能否提供有競爭力的性能降瞳。在傳統(tǒng)的消息中間件 RabbitMQ 中嘱支,就使用內(nèi)存作為默認的存儲介質(zhì),而磁盤作為備選介質(zhì)力崇,以此實現(xiàn)高吞吐和低延遲的特性斗塘。然而,事實上磁盤可以比我們預想的要快亮靴,也可能比我們預想的要慢馍盟,這完全取決于我們?nèi)绾问褂盟?br>

有關測試結果表明,一個由6塊 7200r/min 的 RAID-5 陣列組成的磁盤簇的線性(順序)寫入速度可以達到 600MB/s茧吊,而隨機寫入速度只有 100KB/s贞岭,兩者性能相差6000倍。操作系統(tǒng)可以針對線性讀寫做深層次的優(yōu)化搓侄,比如預讀(read-ahead瞄桨,提前將一個比較大的磁盤塊讀入內(nèi)存)和后寫(write-behind,將很多小的邏輯寫操作合并起來組成一個大的物理寫操作)技術讶踪。順序?qū)懕P的速度不僅比隨機寫盤的速度快芯侥,而且也比隨機寫內(nèi)存的速度快,如下圖所示。


頁緩存的魅力

Kafka 在設計時采用了文件追加的方式來寫入消息柱查,即只能在日志文件的尾部追加新的消息廓俭,并且也不允許修改已寫入的消息,這種方式屬于典型的順序?qū)懕P的操作唉工,所以就算Kafka使用磁盤作為存儲介質(zhì)研乒,它所能承載的吞吐量也不容小覷。但這并不是讓 Kafka 在性能上具備足夠競爭力的唯一因素淋硝,我們不妨繼續(xù)分析雹熬。

頁緩存是操作系統(tǒng)實現(xiàn)的一種主要的磁盤緩存,以此用來減少對磁盤 I/O 的操作谣膳。具體來說竿报,就是把磁盤中的數(shù)據(jù)緩存到內(nèi)存中,把對磁盤的訪問變?yōu)閷?nèi)存的訪問参歹。為了彌補性能上的差異仰楚,現(xiàn)代操作系統(tǒng)越來越“激進地”將內(nèi)存作為磁盤緩存,甚至會非常樂意將所有可用的內(nèi)存用作磁盤緩存犬庇,這樣當內(nèi)存回收時也幾乎沒有性能損失,所有對于磁盤的讀寫也將經(jīng)由統(tǒng)一的緩存侨嘀。

當一個進程準備讀取磁盤上的文件內(nèi)容時臭挽,操作系統(tǒng)會先查看待讀取的數(shù)據(jù)所在的頁(page)是否在頁緩存(pagecache)中,如果存在(命中)則直接返回數(shù)據(jù)咬腕,從而避免了對物理磁盤的 I/O 操作欢峰;如果沒有命中,則操作系統(tǒng)會向磁盤發(fā)起讀取請求并將讀取的數(shù)據(jù)頁存入頁緩存涨共,之后再將數(shù)據(jù)返回給進程纽帖。

同樣,如果一個進程需要將數(shù)據(jù)寫入磁盤举反,那么操作系統(tǒng)也會檢測數(shù)據(jù)對應的頁是否在頁緩存中懊直,如果不存在,則會先在頁緩存中添加相應的頁火鼻,最后將數(shù)據(jù)寫入對應的頁室囊。被修改過后的頁也就變成了臟頁,操作系統(tǒng)會在合適的時間把臟頁中的數(shù)據(jù)寫入磁盤魁索,以保持數(shù)據(jù)的一致性融撞。

Linux 操作系統(tǒng)中的 vm.dirty_background_ratio 參數(shù)用來指定當臟頁數(shù)量達到系統(tǒng)內(nèi)存的百分之多少之后就會觸發(fā) pdflush/flush/kdmflush 等后臺回寫進程的運行來處理臟頁,一般設置為小于10的值即可粗蔚,但不建議設置為0尝偎。與這個參數(shù)對應的還有一個 vm.dirty_ratio 參數(shù),它用來指定當臟頁數(shù)量達到系統(tǒng)內(nèi)存的百分之多少之后就不得不開始對臟頁進行處理鹏控,在此過程中致扯,新的 I/O 請求會被阻擋直至所有臟頁被沖刷到磁盤中趁窃。對臟頁有興趣的讀者還可以自行查閱 vm.dirty_expire_centisecs、vm.dirty_writeback.centisecs 等參數(shù)的使用說明急前。

對一個進程而言醒陆,它會在進程內(nèi)部緩存處理所需的數(shù)據(jù),然而這些數(shù)據(jù)有可能還緩存在操作系統(tǒng)的頁緩存中裆针,因此同一份數(shù)據(jù)有可能被緩存了兩次刨摩。并且,除非使用 Direct I/O 的方式世吨,否則頁緩存很難被禁止澡刹。此外,用過 Java 的人一般都知道兩點事實:對象的內(nèi)存開銷非常大耘婚,通常會是真實數(shù)據(jù)大小的幾倍甚至更多罢浇,空間使用率低下;Java 的垃圾回收會隨著堆內(nèi)數(shù)據(jù)的增多而變得越來越慢沐祷∪卤眨基于這些因素,使用文件系統(tǒng)并依賴于頁緩存的做法明顯要優(yōu)于維護一個進程內(nèi)緩存或其他結構赖临,至少我們可以省去了一份進程內(nèi)部的緩存消耗胞锰,同時還可以通過結構緊湊的字節(jié)碼來替代使用對象的方式以節(jié)省更多的空間。如此兢榨,我們可以在32GB的機器上使用28GB至30GB的內(nèi)存而不用擔心 GC 所帶來的性能問題嗅榕。

此外,即使 Kafka 服務重啟吵聪,頁緩存還是會保持有效凌那,然而進程內(nèi)的緩存卻需要重建。這樣也極大地簡化了代碼邏輯吟逝,因為維護頁緩存和文件之間的一致性交由操作系統(tǒng)來負責帽蝶,這樣會比進程內(nèi)維護更加安全有效。

Kafka 中大量使用了頁緩存澎办,這是 Kafka 實現(xiàn)高吞吐的重要因素之一嘲碱。雖然消息都是先被寫入頁緩存,然后由操作系統(tǒng)負責具體的刷盤任務的局蚀,但在 Kafka 中同樣提供了同步刷盤及間斷性強制刷盤(fsync)的功能麦锯,這些功能可以通過 log.flush.interval.messages、log.flush.interval.ms 等參數(shù)來控制琅绅。

同步刷盤可以提高消息的可靠性扶欣,防止由于機器掉電等異常造成處于頁緩存而沒有及時寫入磁盤的消息丟失。不過筆者并不建議這么做,刷盤任務就應交由操作系統(tǒng)去調(diào)配料祠,消息的可靠性應該由多副本機制來保障骆捧,而不是由同步刷盤這種嚴重影響性能的行為來保障。

Linux 系統(tǒng)會使用磁盤的一部分作為 swap 分區(qū)髓绽,這樣可以進行進程的調(diào)度:把當前非活躍的進程調(diào)入 swap 分區(qū)敛苇,以此把內(nèi)存空出來讓給活躍的進程。對大量使用系統(tǒng)頁緩存的 Kafka 而言顺呕,應當盡量避免這種內(nèi)存的交換枫攀,否則會對它各方面的性能產(chǎn)生很大的負面影響。

我們可以通過修改 vm.swappiness 參數(shù)(Linux 系統(tǒng)參數(shù))來進行調(diào)節(jié)株茶。vm.swappiness 參數(shù)的上限為100来涨,它表示積極地使用 swap 分區(qū),并把內(nèi)存上的數(shù)據(jù)及時地搬運到 swap 分區(qū)中启盛;vm.swappiness 參數(shù)的下限為0蹦掐,表示在任何情況下都不要發(fā)生交換(vm.swappiness = 0 的含義在不同版本的 Linux 內(nèi)核中不太相同,這里采用的是變更后的最新解釋)僵闯,這樣一來卧抗,當內(nèi)存耗盡時會根據(jù)一定的規(guī)則突然中止某些進程。筆者建議將這個參數(shù)的值設置為1棍厂,這樣保留了 swap 的機制而又最大限度地限制了它對 Kafka 性能的影響颗味。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市牺弹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌时呀,老刑警劉巖张漂,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異谨娜,居然都是意外死亡航攒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門趴梢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漠畜,“玉大人,你說我怎么就攤上這事坞靶°灸” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵彰阴,是天一觀的道長瘾敢。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么簇抵? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任庆杜,我火速辦了婚禮,結果婚禮上碟摆,老公的妹妹穿的比我還像新娘晃财。我一直安慰自己,他們只是感情好典蜕,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布断盛。 她就那樣靜靜地躺著,像睡著了一般嘉裤。 火紅的嫁衣襯著肌膚如雪郑临。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天屑宠,我揣著相機與錄音厢洞,去河邊找鬼。 笑死典奉,一個胖子當著我的面吹牛躺翻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卫玖,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼公你,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了假瞬?” 一聲冷哼從身側響起陕靠,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脱茉,沒想到半個月后剪芥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡琴许,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年税肪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榜田。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡益兄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出箭券,到底是詐尸還是另有隱情净捅,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布邦鲫,位于F島的核電站灸叼,受9級特大地震影響神汹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜古今,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一屁魏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捉腥,春花似錦氓拼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拟逮,卻和暖如春撬统,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背敦迄。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工恋追, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人罚屋。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓苦囱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親脾猛。 傳聞我的和親對象是個殘疾皇子撕彤,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

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