RocketMQ存儲(chǔ)設(shè)計(jì)精髓
?
點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)
另外在進(jìn)行消息消費(fèi)的時(shí)候,RocketMQ如何能借助自身的存儲(chǔ)設(shè)計(jì)快速檢索到對(duì)應(yīng)的消息也是非常重要的,因此本文主要對(duì)RocketMQ存儲(chǔ)設(shè)計(jì)進(jìn)行了設(shè)計(jì)分析。
存儲(chǔ)結(jié)構(gòu)
RocketMQ對(duì)應(yīng)的存儲(chǔ)文件主要包括三類,分別是Commitlog文件、ConsumeQueue文件以及Index文件,每一個(gè)文件都有其特殊的使命。
Commitlog文件
當(dāng)生產(chǎn)者將消息發(fā)送到RocketMQ的Broker之后,需要將消息進(jìn)行持久化存儲(chǔ),防止消息數(shù)據(jù)丟失。RocketMQ將消息數(shù)據(jù)寫入存儲(chǔ)文件CommitLog中,按照消息的發(fā)送順序?qū)懭胛募?dāng)中,每個(gè)文件的大小約為1G,當(dāng)達(dá)到文件大小限制后,就會(huì)創(chuàng)建新的CommitLog文件。RocketMQ作為消息中間件來(lái)說(shuō),最主要的數(shù)據(jù)流程就是基于主題的發(fā)布-訂閱模式進(jìn)行消息的發(fā)布以及消費(fèi),那么當(dāng)消費(fèi)者根據(jù)自己訂閱的Topic進(jìn)行消息消費(fèi)的時(shí)候,Broker怎么在那么多的CommitLog文件中找到對(duì)應(yīng)Topic的消息數(shù)據(jù)呢?

大家可以想一想,CommitLog文件中的消息數(shù)據(jù)是一條一條順序?qū)懙?,最笨的方法就是遍歷文件,作為一款高性能的消息中間件,顯然這不是一個(gè)好的解決方案。
就像從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)的時(shí)候,遍歷的效率肯定是很低的。那么我們可不可以借助數(shù)據(jù)庫(kù)提升數(shù)據(jù)查詢的方式,使用索引來(lái)加快消息數(shù)據(jù)的查詢呢?答案是肯定的。就像Mysql中的索引本身需要文件保存一樣,在RocketMQ中也有單獨(dú)保存索引的文件,就是ConsumerQueue文件。
ConsumerQueue文件
在RocketMQ中,每個(gè)Topic對(duì)應(yīng)多個(gè)MessageQueue,每個(gè)MessageQueue對(duì)應(yīng)一組ConsumerQueue文件索引文件。ConsumerQueue文件中存儲(chǔ)了消息相對(duì)于CommitLog文件的offset偏移量,CommitLog文件本身實(shí)際上也是通過(guò)偏移量來(lái)進(jìn)行命名如第一個(gè)文件是0000000000000,那么第二文件就是消息總量之和00000001232321,往后新的文件再進(jìn)行累計(jì)。為什么這么做呢?主要就是在進(jìn)行消息查找的時(shí)候根據(jù)消息的偏移量通過(guò)二分查找快速定位具體的CommitLog文件,提升消息查找效率。需要說(shuō)明的是,Broker在進(jìn)行消息寫入CommitLog文件中就會(huì)異步將其對(duì)應(yīng)的偏移量寫入ConsumerQueue文件中。

在ConsumerQueue文件中實(shí)際存儲(chǔ)了CommitLog文件的offset偏移量、消息長(zhǎng)度以及tag的hashcode,組成20字節(jié)的block塊。其在Broker上面的存儲(chǔ)路徑大致是:.../store/consumequeue/{topic}/{queueid}/{file}。
其中topic就是生產(chǎn)中訂閱的主題,因此消費(fèi)者在消費(fèi)消息的時(shí)候,Broker會(huì)根據(jù)其對(duì)應(yīng)的Topic找到對(duì)應(yīng)的 ?ConsumerQueue文件,進(jìn)而找到其索引位置,再到CommitLog文件中直接定位具體的消息。
Index文件
另外RocketMQ的特性功能就是可以實(shí)現(xiàn)按照消息的屬性進(jìn)行消息搜索,即建立了索引 Key 的 hashcode 與物理偏移量的映射關(guān)系,根據(jù) key 先快速定義到 commitlog 文件。
存儲(chǔ)性能設(shè)計(jì)精髓
上文中為大家闡述了RocketMQ關(guān)于存儲(chǔ)結(jié)構(gòu)的設(shè)計(jì),優(yōu)秀的存儲(chǔ)設(shè)計(jì)師實(shí)現(xiàn)高性能讀寫的前提。那么除了存儲(chǔ)結(jié)構(gòu)的設(shè)計(jì),RocketMQ也使用了一些性能優(yōu)化手段來(lái)實(shí)現(xiàn)其強(qiáng)大的消息吞吐能力。消息順序?qū)?/span>
前文中說(shuō)過(guò),消息進(jìn)入RocketMQ之后,消息數(shù)據(jù)是通過(guò)順序?qū)懙姆绞铰涞紺ommitLog文件中的。那么這里面就涉及兩個(gè)問(wèn)題,為什么進(jìn)行順序?qū)懸约笆遣皇侵苯訉懘疟P文件。
1、為什么要順序?qū)懀?/span>
當(dāng)新的數(shù)據(jù)到來(lái)時(shí),只要在之前的文件末尾進(jìn)行數(shù)據(jù)追加就可以,這樣的數(shù)據(jù)寫入效率要比隨機(jī)寫入的效率高。2、每次數(shù)據(jù)寫入的時(shí)候是直接寫磁盤文件嗎?
我們可以反過(guò)想,如果每次都是落盤寫入的話實(shí)際效率是不高的,無(wú)法滿足消息中間件這種高吞吐的性能要求,因此RocketMQ實(shí)際是借助操作系統(tǒng)的page cache來(lái)提升寫入效率的,消息并不是直接寫入磁盤,而是先寫入操作系統(tǒng)的page cache,然后再通過(guò)異步刷盤的方式,寫入CommitLog文件中,這樣借助順序?qū)懸约跋到y(tǒng)的page cache可以時(shí)間近乎內(nèi)存的數(shù)據(jù)寫入效率。同步刷盤和異步刷盤
異步刷盤
剛才所說(shuō)的異步寫入,其實(shí)就是RocketMQ的異步刷盤模式,但是大家想想這個(gè)模式有沒(méi)有什么問(wèn)題。為了提升數(shù)據(jù)吞吐量,消息數(shù)據(jù)過(guò)來(lái)后,并沒(méi)有直接寫盤,而是在系統(tǒng)中的page cache中。那么此時(shí)如果Broker宕機(jī)了,那么此時(shí)的消息數(shù)據(jù)是容易丟失的。所以雖然異步刷盤的寫入效率高但是也存在數(shù)據(jù)丟失的風(fēng)險(xiǎn)。同步刷盤
在同步刷盤的場(chǎng)景下,當(dāng)Broker接受到對(duì)應(yīng)的消息之后,Broker將會(huì)把這條消息刷入磁盤的CommitLog中,才會(huì)返回確認(rèn)消息給生產(chǎn)者。如果在進(jìn)行消息寫入的時(shí)候Broker掛了,那么生產(chǎn)者會(huì)感受到消息投遞失敗,一般都會(huì)都有消息重新發(fā)送的重試邏輯。這樣看消息似乎不會(huì)丟失了,但是由于每次都是先落盤,就會(huì)導(dǎo)致數(shù)據(jù)寫入性能下降。MMAP
在RocketMQ中使用了mmap技術(shù)來(lái)實(shí)現(xiàn)Conmmitlog文件的高性能讀寫,mmap就是一種內(nèi)存映射文件的方法,對(duì)于傳統(tǒng)的文件IO交互來(lái)說(shuō),需要經(jīng)過(guò)多次的數(shù)據(jù)復(fù)制過(guò)程才能將用戶進(jìn)程的數(shù)據(jù)寫入硬盤或者讀入程序。而mmap可以直接將虛擬內(nèi)存中的文件與硬盤中文件地址進(jìn)行映射,減少了數(shù)據(jù)拷貝的過(guò)程,從而提升了數(shù)據(jù)寫入的效率。
總結(jié)
本文主要對(duì)RocketMQ的存儲(chǔ)設(shè)計(jì)進(jìn)行了分析,圍繞如何實(shí)現(xiàn)高性能消息寫入和查詢展開了闡述,希望在分析這些優(yōu)秀中間的具體實(shí)現(xiàn)過(guò)程中,我們可以將這些優(yōu)秀設(shè)計(jì)融入到具體的項(xiàng)目實(shí)踐中,當(dāng)我們遇到類似的問(wèn)題的時(shí)候可以借助于這些設(shè)計(jì)思想來(lái)解決實(shí)際的問(wèn)題。往期推薦
2、銷量5年暴增25倍的TWS耳機(jī)你買了嗎?售價(jià)或會(huì)再跌20%
3、2021年程序員們都在用的神級(jí)數(shù)據(jù)庫(kù)
4、Windows重要功能被閹割,全球用戶怒噴數(shù)月后微軟終于悔改
5、牛逼!國(guó)產(chǎn)開源的遠(yuǎn)程桌面火了,只有9MB 支持自建中繼器!

點(diǎn)分享

點(diǎn)收藏

點(diǎn)點(diǎn)贊

點(diǎn)在看
評(píng)論
圖片
表情
