1.CommitLog基于os cache提升寫(xiě)性能的回顧
要搞明白到底什么時(shí)候從Master Broker拉取消息,什么時(shí)候從Slave Broker拉取消息,首先得搞明白一個(gè)很關(guān)鍵的問(wèn)題,那就是拉取消息的時(shí)候必然會(huì)先讀取ConsumeQueue文件,這個(gè)ConsumeQueue文件的讀取是如何優(yōu)化的?
broker收到一條消息,會(huì)寫(xiě)入CommitLog文件,但是會(huì)先把CommitLog文件中的數(shù)據(jù)寫(xiě)入os cache(操作系統(tǒng)管理的緩存)中去,如下圖

然后os自己有后臺(tái)線程,過(guò)一段時(shí)間后會(huì)異步把os cache緩存中的CommitLog文件的數(shù)據(jù)刷入磁盤(pán)中去,如下圖。
寫(xiě)入CommitLog時(shí)先進(jìn)入os cache緩存,而不是直接進(jìn)入磁盤(pán)的機(jī)制,就可以實(shí)現(xiàn)broker寫(xiě)CommitLog文件的性能是內(nèi)存寫(xiě)級(jí)別的,這才能實(shí)現(xiàn)broker超高的消息接入吞吐量。

2、第一個(gè)很關(guān)鍵的問(wèn)題:ConsumeQueue文件也是基于os cache的
第一個(gè)很關(guān)鍵的問(wèn)題,那就是ConsumeQueue會(huì)被大量的消費(fèi)者發(fā)送的請(qǐng)求給高并發(fā)的讀取,所以ConsumeQueue文件的讀操作是非常頻繁的,而且同時(shí)會(huì)極大的影響到消費(fèi)者進(jìn)行消息拉取的性能和消費(fèi)吞吐量。
所以實(shí)際上broker對(duì)ConsumeQueue文件同樣也是基于os cache來(lái)進(jìn)行優(yōu)化的,
也就是說(shuō),對(duì)于Broker機(jī)器的磁盤(pán)上的大量的ConsumeQueue文件,在寫(xiě)入的時(shí)候也都是優(yōu)先進(jìn)入os cache中的.
而且os自己有一個(gè)優(yōu)化機(jī)制,就是讀取一個(gè)磁盤(pán)文件的時(shí)候,他會(huì)自動(dòng)把磁盤(pán)文件的一些數(shù)據(jù)緩存到os cache中。
ConsumeQueue文件主要是存放消息的offset,所以每個(gè)文件很小,30萬(wàn)條消息的offset就只有5.72MB而已。所以實(shí)際上ConsumeQueue文件們是不占用多少磁盤(pán)空間的,他們整體數(shù)據(jù)量很小,幾乎可以完全被os緩存在內(nèi)存cache里。
所以實(shí)際上在消費(fèi)者機(jī)器拉取消息的時(shí)候,第一步大量的頻繁讀取ConsumeQueue文件,幾乎可以說(shuō)就是跟讀內(nèi)存里的數(shù)據(jù)的性能是一樣的,通過(guò)這個(gè)就可以保證數(shù)據(jù)消費(fèi)的高性能以及高吞吐。

3、第二個(gè)關(guān)鍵問(wèn)題:CommitLog是基于os cache+磁盤(pán)一起讀取的
接著我們來(lái)看第二個(gè)比較關(guān)鍵的問(wèn)題,在進(jìn)行消息拉取的時(shí)候,先讀os cache里的少量ConsumeQueue的數(shù)據(jù),這個(gè)性能是極高的,然后第二步就是要根據(jù)你讀取到的offset去CommitLog里讀取消息的完整數(shù)據(jù)了。
從CommitLog里讀取消息完整數(shù)據(jù)是如何讀取的?是從os cache里讀?。窟€是從磁盤(pán)里讀???
答案是:兩者都有
因?yàn)镃ommitLog是用來(lái)存放消息的完整數(shù)據(jù)的,所以內(nèi)容量是很大的,畢竟他一個(gè)文件就要1GB,所以整體完全有可能多達(dá)幾個(gè)TB。
所以你思考一下,這么多的數(shù)據(jù),可能都放在os cache里嗎?
明顯是不可能的,因?yàn)閛s cache用的也是機(jī)器的內(nèi)存,一般多也就幾十個(gè)GB而已,何況Broker自身的JVM也要用一些內(nèi)存,留個(gè)os cache的內(nèi)存只是一部分罷了,比如10GB~20GB的內(nèi)存,所以os cache對(duì)于CommitLog而言,是無(wú)法把他全部數(shù)據(jù)都放在里面給你讀取的!
也就是說(shuō),os cache對(duì)于CommitLog而言,主要是提升文件寫(xiě)入性能,當(dāng)你不停的寫(xiě)入的時(shí)候,很多最新寫(xiě)入的數(shù)據(jù)都會(huì)先停留在os cache里,比如這可能有10GB~20GB的數(shù)據(jù)。
之后os會(huì)自動(dòng)把cache里的比較舊的一些數(shù)據(jù)刷入磁盤(pán)里,騰出來(lái)空間給更新寫(xiě)入的數(shù)據(jù)放在os cache里,所以大部分?jǐn)?shù)據(jù)可能多達(dá)幾個(gè)TB都是在磁盤(pán)上的。
如圖:

第一種可能:
如果你讀取的是那種剛剛寫(xiě)入CommitLog的數(shù)據(jù),那么大概率他們還停留在os cache中,此時(shí)你可以順利的直接從os cache里讀取CommitLog中的數(shù)據(jù),這個(gè)就是內(nèi)存讀取,性能是很高的。
第二種可能:
你也許讀取的是比較早之前寫(xiě)入CommitLog的數(shù)據(jù),那些數(shù)據(jù)早就被刷入磁盤(pán)了,已經(jīng)不在os cache里了,那么此時(shí)你就只能從磁盤(pán)上的文件里讀取了,這個(gè)性能是比較差一些的。
4、什么時(shí)候會(huì)從os cache讀?什么時(shí)候會(huì)從磁盤(pán)讀?
如果你的消費(fèi)者機(jī)器一直快速的在拉取和消費(fèi)處理,緊緊的跟上了生產(chǎn)者寫(xiě)入broker的消息速率,那么你每次拉取幾乎都是在拉取最近人家剛寫(xiě)入CommitLog的數(shù)據(jù),那幾乎都在os cache里。
但是如果broker的負(fù)載很高,導(dǎo)致你拉取消息的速度很慢,或者是你自己的消費(fèi)者機(jī)器拉取到一批消息之后處理的時(shí)候性能很低,處理的速度很慢,這都會(huì)導(dǎo)致你跟不上生產(chǎn)者寫(xiě)入的速率。
比如人家都寫(xiě)入10萬(wàn)條數(shù)據(jù)了,結(jié)果你才拉取了2萬(wàn)條數(shù)據(jù),此時(shí)有5萬(wàn)條最新的數(shù)據(jù)是在os cache里,有3萬(wàn)條你還沒(méi)拉取的數(shù)據(jù)是在磁盤(pán)里,那么當(dāng)后續(xù)你再拉取的時(shí)候,必然很大概率是從磁盤(pán)里讀取早就刷入磁盤(pán)的3萬(wàn)條數(shù)據(jù)。
接著之前在os cache里的5萬(wàn)條數(shù)據(jù)可能又被刷入磁盤(pán)了,取而代之的是更新的幾萬(wàn)條數(shù)據(jù)在os cache里,然后你再次拉取的時(shí)候,又會(huì)從磁盤(pán)里讀取刷入磁盤(pán)里的5萬(wàn)條數(shù)據(jù),相當(dāng)于你每次都在從磁盤(pán)里讀取數(shù)據(jù)了!
5、Master Broker什么時(shí)候會(huì)讓你從Slave Broker拉取數(shù)據(jù)?


所以他經(jīng)過(guò)上述判斷,會(huì)發(fā)現(xiàn)此時(shí)你很大概率會(huì)從磁盤(pán)里加載3萬(wàn)條消息出來(lái)!他會(huì)認(rèn)為,出現(xiàn)這種情況,很可能是因?yàn)樽约鹤鳛閙aster broker負(fù)載太高了,導(dǎo)致沒(méi)法及時(shí)的把消息給你,所以你落后的進(jìn)度比較多。
這個(gè)時(shí)候,他就會(huì)告訴你,我這次給你從磁盤(pán)里讀取3萬(wàn)條消息,但是下次你還是從slave broker去拉取吧!