本篇文章給大家分享的是有關(guān)Kafka對(duì)page cache與buffer cache的關(guān)系是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、富裕網(wǎng)絡(luò)推廣、微信小程序開發(fā)、富裕網(wǎng)絡(luò)營銷、富裕企業(yè)策劃、富裕品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供富裕建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com
前言
關(guān)于Kafka的一個(gè)靈魂拷問:它為什么這么快?
或者說,為什么它能做到如此大的吞吐量和如此低的延遲?
有很多文章已經(jīng)對(duì)這個(gè)問題給出了回答,但只重點(diǎn)研究其中的一個(gè)方向,即對(duì)page cache的使用。先簡單地認(rèn)識(shí)一下Linux系統(tǒng)中的page cache(順便也認(rèn)識(shí)一下buffer cache)。
執(zhí)行free命令,注意到會(huì)有兩列名為buffers和cached,也有一行名為“-/+ buffers/cache”。
~ free -m
total used free shared buffers cached
Mem: 128956 96440 32515 0 5368 39900
-/+ buffers/cache: 51172 77784
Swap: 16002 0 16001
其中,cached列表示當(dāng)前的頁緩存(page cache)占用量,buffers列表示當(dāng)前的塊緩存(buffer cache)占用量。用一句話來解釋:page cache用于緩存文件的頁數(shù)據(jù),buffer cache用于緩存塊設(shè)備(如磁盤)的塊數(shù)據(jù)。頁是邏輯上的概念,因此page cache是與文件系統(tǒng)同級(jí)的;塊是物理上的概念,因此buffer cache是與塊設(shè)備驅(qū)動(dòng)程序同級(jí)的。
page cache與buffer cache的共同目的都是加速數(shù)據(jù)I/O:寫數(shù)據(jù)時(shí)首先寫到緩存,將寫入的頁標(biāo)記為dirty,然后向外部存儲(chǔ)flush,也就是緩存寫機(jī)制中的write-back(另一種是write-through,Linux未采用);讀數(shù)據(jù)時(shí)首先讀取緩存,如果未命中,再去外部存儲(chǔ)讀取,并且將讀取來的數(shù)據(jù)也加入緩存。操作系統(tǒng)總是積極地將所有空閑內(nèi)存都用作page cache和buffer cache,當(dāng)內(nèi)存不夠用時(shí)也會(huì)用LRU等算法淘汰緩存頁。
在Linux 2.4版本的內(nèi)核之前,page cache與buffer cache是完全分離的。但是,塊設(shè)備大多是磁盤,磁盤上的數(shù)據(jù)又大多通過文件系統(tǒng)來組織,這種設(shè)計(jì)導(dǎo)致很多數(shù)據(jù)被緩存了兩次,浪費(fèi)內(nèi)存。所以在2.4版本內(nèi)核之后,兩塊緩存近似融合在了一起:如果一個(gè)文件的頁加載到了page cache,那么同時(shí)buffer cache只需要維護(hù)塊指向頁的指針就可以了。只有那些沒有文件表示的塊,或者繞過了文件系統(tǒng)直接操作(如dd命令)的塊,才會(huì)真正放到buffer cache里。因此,我們現(xiàn)在提起page cache,基本上都同時(shí)指page cache和buffer cache兩者,本文之后也不再區(qū)分,直接統(tǒng)稱為page cache。
下圖近似地示出32-bit Linux系統(tǒng)中可能的一種page cache結(jié)構(gòu),其中block size大小為1KB,page size大小為4KB。
page cache中的每個(gè)文件都是一棵基數(shù)樹(radix tree,本質(zhì)上是多叉搜索樹),樹的每個(gè)節(jié)點(diǎn)都是一個(gè)頁。根據(jù)文件內(nèi)的偏移量就可以快速定位到所在的頁。
接下來就可以把Kafka扯進(jìn)來了。
Kafka為什么不自己管理緩存,而非要用page cache?原因有如下三點(diǎn):
JVM中一切皆對(duì)象,數(shù)據(jù)的對(duì)象存儲(chǔ)會(huì)帶來所謂object overhead,浪費(fèi)空間;
如果由JVM來管理緩存,會(huì)受到GC的影響,并且過大的堆也會(huì)拖累GC的效率,降低吞吐量;
一旦程序崩潰,自己管理的緩存數(shù)據(jù)會(huì)全部丟失。
Kafka三大件(broker、producer、consumer)與page cache的關(guān)系可以用下面的簡圖來表示。
producer生產(chǎn)消息時(shí),會(huì)使用pwrite()系統(tǒng)調(diào)用【對(duì)應(yīng)到Java NIO中是FileChannel.write() API】按偏移量寫入數(shù)據(jù),并且都會(huì)先寫入page cache里。consumer消費(fèi)消息時(shí),會(huì)使用sendfile()系統(tǒng)調(diào)用【對(duì)應(yīng)FileChannel.transferTo() API】,零拷貝地將數(shù)據(jù)從page cache傳輸?shù)絙roker的Socket buffer,再通過網(wǎng)絡(luò)傳輸。
圖中沒有畫出來的還有l(wèi)eader與follower之間的同步,這與consumer是同理的:只要follower處在ISR中,就也能夠通過零拷貝機(jī)制將數(shù)據(jù)從leader所在的broker page cache傳輸?shù)絝ollower所在的broker。
同時(shí),page cache中的數(shù)據(jù)會(huì)隨著內(nèi)核中flusher線程的調(diào)度以及對(duì)sync()/fsync()的調(diào)用寫回到磁盤,就算進(jìn)程崩潰,也不用擔(dān)心數(shù)據(jù)丟失。另外,如果consumer要消費(fèi)的消息不在page cache里,才會(huì)去磁盤讀取,并且會(huì)順便預(yù)讀出一些相鄰的塊放入page cache,以方便下一次讀取。
由此我們可以得出重要的結(jié)論:如果Kafka producer的生產(chǎn)速率與consumer的消費(fèi)速率相差不大,那么就能幾乎只靠對(duì)broker page cache的讀寫完成整個(gè)生產(chǎn)-消費(fèi)過程,磁盤訪問非常少。并且Kafka持久化消息到各個(gè)topic的partition文件時(shí),是只追加的順序?qū)?,充分利用了磁盤順序訪問快的特性,效率高。
注意事項(xiàng)與相關(guān)參數(shù)
對(duì)于單純運(yùn)行Kafka的集群而言,首先要注意的就是為Kafka設(shè)置合適(不那么大)的JVM堆大小。從上面的分析可知,Kafka的性能與堆內(nèi)存關(guān)系并不大,而對(duì)page cache需求巨大。根據(jù)經(jīng)驗(yàn)值,為Kafka分配5~8GB的堆內(nèi)存就已經(jīng)足足夠用了,將剩下的系統(tǒng)內(nèi)存都作為page cache空間,可以最大化I/O效率。
另一個(gè)需要特別注意的問題是lagging consumer,即那些消費(fèi)速率慢、明顯落后的consumer。它們要讀取的數(shù)據(jù)有較大概率不在broker page cache中,因此會(huì)增加很多不必要的讀盤操作。比這更壞的是,lagging consumer讀取的“冷”數(shù)據(jù)仍然會(huì)進(jìn)入page cache,污染了多數(shù)正常consumer要讀取的“熱”數(shù)據(jù),連帶著正常consumer的性能變差。在生產(chǎn)環(huán)境中,這個(gè)問題尤為重要。
前面已經(jīng)說過,page cache中的數(shù)據(jù)會(huì)隨著內(nèi)核中flusher線程的調(diào)度寫回磁盤。與它相關(guān)的有以下4個(gè)參數(shù),必要時(shí)可以調(diào)整。
/proc/sys/vm/dirty_writeback_centisecs:flush檢查的周期。單位為0.01秒,默認(rèn)值500,即5秒。每次檢查都會(huì)按照以下三個(gè)參數(shù)控制的邏輯來處理。
/proc/sys/vm/dirty_expire_centisecs:如果page cache中的頁被標(biāo)記為dirty的時(shí)間超過了這個(gè)值,就會(huì)被直接刷到磁盤。單位為0.01秒。默認(rèn)值3000,即半分鐘。
/proc/sys/vm/dirty_background_ratio:如果dirty page的總大小占空閑內(nèi)存量的比例超過了該值,就會(huì)在后臺(tái)調(diào)度flusher線程異步寫磁盤,不會(huì)阻塞當(dāng)前的write()操作。默認(rèn)值為10%。
/proc/sys/vm/dirty_ratio:如果dirty page的總大小占總內(nèi)存量的比例超過了該值,就會(huì)阻塞所有進(jìn)程的write()操作,并且強(qiáng)制每個(gè)進(jìn)程將自己的文件寫入磁盤。默認(rèn)值為20%。
由此可見,調(diào)整空間比較靈活的是參數(shù)2、3,而盡量不要達(dá)到參數(shù)4的閾值,代價(jià)太大了。
以上就是Kafka對(duì)page cache與buffer cache的關(guān)系是什么,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。