RocketMQ中的消息存儲(chǔ)在本地文件系統(tǒng)中晴股,這些相關(guān)文件默認(rèn)在當(dāng)前用戶主目錄下的store目錄中。
- abort:該文件在Broker啟動(dòng)后會(huì)自動(dòng)創(chuàng)建肺魁,正常關(guān)閉Broker队魏,該文件會(huì)自動(dòng)消失。若在沒有啟動(dòng)Broker的情況下,發(fā)現(xiàn)這個(gè)文件是存在的胡桨,則說明之前Broker的關(guān)閉時(shí)非正常關(guān)閉
- checkpoint:其中存儲(chǔ)著commitlog官帘、consumequeue、index文件的最后刷盤時(shí)間戳
- commitlog:存放commitlog文件昧谊,而消息是寫在commitlog文件中的
- config:存放著Broker運(yùn)行期間的一些配置數(shù)據(jù)
- consumequeue:存放consumequeue文件刽虹,隊(duì)列存放在這個(gè)目錄
- index:存放著消息索引文件indexFile
- lock:運(yùn)行期間使用到的全局資源鎖
1.commitlog文件
說明:在很多資料中commitlog目錄中的文件簡(jiǎn)單就稱為commitlog文件。但在源碼中呢诬,該文件被命名為mappedFile涌哲。
目錄與文件
commitlog目錄中存放著很多的mappedFile文件,當(dāng)前Broker中的所有消息都落盤到這些mappedFile文件中尚镰。mappedFile文件大小為1G阀圾。文件名由20位十進(jìn)制數(shù)構(gòu)成,表示當(dāng)前文件的第一天消息的起始位置偏移量狗唉。
第一個(gè)文件名一定是20位的0初烘。因?yàn)榈谝粋€(gè)文件的第一條消息的偏移量commitlog offset為0
當(dāng)?shù)谝粋€(gè)文件放滿時(shí),則會(huì)自動(dòng)生成第二個(gè)文件繼續(xù)存放消息分俯。加入第一個(gè)文件大小是1073741820字節(jié)肾筐,則第二個(gè)文件名就是 00000000001073741824 。
以此類推缸剪,第n個(gè)文件名應(yīng)該是n-1個(gè)文件大小之和吗铐。
一個(gè)Broker中所有mappedFile文件的commitlog offset是連續(xù)的
需要注意的是,一個(gè)Broker中僅包含一個(gè)commitlog目錄杏节,所有的mappedFile文件都是存放在該目錄中的唬渗。即無論當(dāng)前Broker中存放著多少Topic的消息,這些消息都是被順序?qū)懭氲搅薽appedFile文件中的奋渔。也就是說镊逝,這些消息在Broker中存放時(shí)并沒有被按照Topic進(jìn)行分類存放。
mappedFile文件時(shí)順序讀寫的文件卒稳,所以其訪問效率很高
消息單元
mappedFile文件內(nèi)容由一個(gè)個(gè)的消息單元
構(gòu)成。每個(gè)消息單元包含消息總長(zhǎng)度MsgLen他巨、消息的物理位置physicalOffset充坑、消息內(nèi)容Body、消息體長(zhǎng)度BodyLength染突、消息主題Topic捻爷、Topic長(zhǎng)度TopicLength、消息生產(chǎn)者BornHost份企、消息發(fā)送時(shí)間戳BornTimestamp也榄、消息所在的隊(duì)列QueueId、消息在Queue中存儲(chǔ)的偏移量QueueOffset等近20個(gè)相關(guān)屬性。
2.consumequeue
目錄與文件
為了提高效率甜紫,會(huì)為每個(gè)Topic在~/store/consumequqeue中創(chuàng)建一個(gè)目錄降宅,目錄名稱為Topic名稱。在該Topic目錄下囚霸,會(huì)再為每個(gè)該Topic的Queue建立一個(gè)目錄腰根,目錄名為queueId。每個(gè)目錄中存放著若干consumequeue文件拓型,consumequeue文件是commitlog的索引文件额嘿,可以根據(jù)consumequeue定位到具體的消息。
consumequeue文件名也是由20位數(shù)字構(gòu)成劣挫,表示當(dāng)前文件的第一個(gè)索引條目的起始位移偏移量册养。與mappedFiel文件名不同的是,其后續(xù)文件名是固定的压固。因?yàn)閏onsumequeue文件大小是固定不變的球拦。
索引條目
每個(gè)consumequeue文件可以包含30W個(gè)索引條目,每個(gè)索引條目包含了三個(gè)消息的重要屬性:消息在mappedFile文件中的偏移量CommitLog Offset邓夕、消息長(zhǎng)度刘莹、消息Tag的hashcode值。這三個(gè)屬性占20個(gè)字節(jié)焚刚,所以每個(gè)文件打大小是固定的30W * 20字節(jié)点弯。
一個(gè)consumequeue文件中所有的消息Topic一定是相同的。但每條消息的Tag可能是不同的
3.對(duì)文件的讀寫
消息寫入
一條消息進(jìn)入到Broker后經(jīng)歷了以下幾個(gè)過程才最終被持久化矿咕。
- Broker根據(jù)queueId抢肛,獲取到該消息對(duì)應(yīng)索引條目要在consumequeue目錄中的寫入偏移量,即QueueOffset碳柱。
- 將queueId捡絮、queueOffset等數(shù)據(jù),與消息一起封裝為消息單元
- 將消息單元寫入到commitlog
- 同時(shí)莲镣,形成消息索引條目
- 將消息索引條目分發(fā)到相應(yīng)的consumequeue
消息拉取
- 當(dāng)Consumer來拉取消息時(shí)會(huì)經(jīng)歷以下幾個(gè)步驟:
consumer獲取到消費(fèi)消息所在Queue的消費(fèi)偏移量offset福稳,計(jì)算出其要消費(fèi)消息的offset
offset即消費(fèi)進(jìn)度,consumer對(duì)某個(gè)Queue的消費(fèi)offset瑞侮,即消費(fèi)到了該Queue的第幾條消息
- Consumer向Broker發(fā)送拉取請(qǐng)求的圆,其中會(huì)包含其他要拉取消息的Queue、消息offset及消息Tag半火。
- Broker計(jì)算在consumerqueue中的queueOffset
- 從該queueOffset處開始向后查找第一個(gè)指定Tag的索引條目越妈。
- 解析該索引條目的前8個(gè)字節(jié),即可定位到該消息在commitlog中的commitlog offset
- 從對(duì)應(yīng)commitlog offset中讀取消息單元钮糖,并發(fā)送給Consumer
性能提升
RocketMQ中梅掠,無論是消息本身還是消息索引,都是存儲(chǔ)在磁盤上的。系統(tǒng)通過一系列的機(jī)制大大提升了性能阎抒。
首先酪我,RocketMQ對(duì)文件的讀寫操作是通過mmap零拷貝
進(jìn)行的,將對(duì)文件的操作轉(zhuǎn)化為直接對(duì)內(nèi)存地址進(jìn)行操作挠蛉,從而極大地提高了文件的讀寫效率祭示。
其次,consumequeue中的數(shù)據(jù)是順序存放的谴古,還引入了PageCache的 預(yù)讀取機(jī)制
质涛,使得對(duì)consumequeue文件得讀取幾乎接近于內(nèi)存讀取,即使在有消息堆積得情況下也不會(huì)影響性能掰担。
mmap 通過內(nèi)存映射汇陆,將文件映射到內(nèi)核緩沖區(qū),同時(shí)带饱,用戶空間可以共享內(nèi)核空間的數(shù)據(jù)毡代。這樣,在進(jìn)行網(wǎng)絡(luò)傳輸時(shí)勺疼,就可以減少內(nèi)核空間到用戶空間的拷貝次數(shù)教寂。
PageCache機(jī)制,頁緩存機(jī)制执庐,是OS對(duì)文件得緩存機(jī)制酪耕,用于加速對(duì)文件得讀寫操作。一般來說轨淌,程序?qū)ξ募M(jìn)行順序讀寫的速度幾乎接近于內(nèi)存讀寫速度迂烁,主要原因是由于OS使用PageCache機(jī)制對(duì)讀寫訪問操作進(jìn)行性能優(yōu)化,將一部分的內(nèi)存用作PageCache递鹉。
4.與Kafka的對(duì)比
Rocket的很多思想來源于Kafka盟步,其中commitlog與consumequeue就是。
RocketMQ中的commitlog目錄與consumequeue的結(jié)合就類似于Kafka中的partition分區(qū)目錄躏结。mappedFile文件就類似與Kafka中的segment段却盘。
Kafka中的Topic的消息被分割為一個(gè)或多個(gè)partition。partition是一個(gè)物理概念媳拴,對(duì)應(yīng)到系統(tǒng)上就是topic目錄下的一個(gè)或多個(gè)目錄黄橘。每個(gè)partition中包含的文件稱為segment,是具體存放消息的文件禀挫。
Kafka中消息存放的目錄結(jié)構(gòu)是:topic目錄下有partition目錄旬陡,partition目錄下有segment文件