RocketMQ存儲篇——整體結構以及MappedFile講解

  1. 存儲篇
  2. 大文件的磁盤操作——MapedFile

1 存儲篇
1.1 整體結構
存儲層的結構如下圖所示,業務層均通過DefaultMessageStore類提供的方法作爲統一入口訪問底層文件。RocketMQ底層有6類文件,對於不同類型的文件在存儲邏輯層採用不同的類提供服務,其中三類大文件:Index文件由IndexService類提供服務,consumequeue文件由Consumequeue類提供服務,commitlog文件由CommitLog類提供服務,還有兩類小文件:checkpoint文件由StoreCheckPoint類提供訪問服務、config目錄下面的配置文件(以json格式存儲)由ConfigMananger類提供訪問服務;
對於index/consumequeue/commitlog這三類大文件,爲了提供讀寫性能,底層採用java.nio.MappedByteBuffer類,該類是文件內存映射方案,支持隨機讀/順序寫操作,爲了便於存儲邏輯層操作大文件,將該類封裝成MapedFile類;對於每類大文件,在存儲時分隔成多個固定大小的文件,其中每分隔的文件的文件名爲前面所有文件的大小+1,即爲文件的起始偏移量,從而實現了整個大文件的串聯,每個固定大小的文件均由MapedFile類提供操作服務;MapedFile類提供了順序寫、隨機讀、內存數據刷盤、內存清理等與文件相關的服務。

1.2 大文件的磁盤操作——MapedFile
對於commitlog、consumequeue、index三類大文件進行磁盤讀寫操作,均是通過MapedFile類來完成。該類的成員變量如下圖所示,就是映射文件的屬性信息;
這裏寫圖片描述
該類有如下主要的功能:
1.2.1 向文件順序寫操作(appendMessage)
有兩種順序寫的方法,第一種是供commitlog使用,傳入消息內容,由CommitLog按照規定的格式構造二進制信息並順序寫,方法:appendMessage(final Object msg, final AppendMessageCallback cb);第二種是由調用者將消息按照規定的格式組裝成二進制信息之後再傳入,方法:appendMessage(final byte[] data);
一、appendMessage(final Object msg, final AppendMessageCallback cb)方法
該方法中msg是MessageExtBrokerInner對象。具體的順序寫操作在AppendMessageCallback回調類的doAppend(final long fileFromOffset, final ByteBuffer byteBuffer,final int maxBlank, final Object msg)方法中實現。目前只有CommitLog的內部類DefaultAppendMessageCallback實現了該回調類的方法,故該順序寫方法只有在寫入commitlog文件是才調用。
二、appendMessage(final byte[] data)方法
1)獲取當前內存對象的寫入位置(wrotePostion變量值);
2)若當前寫入位置加上二進制消息的長度小於文件大小,即剩餘的空間夠寫入該消息,則由內存對象mappedByteBuffer創建一個指向同一塊內存的ByteBuffer對象,並將內存對象的寫入指針指向寫入位置;然後將該二進制信息寫入該內存對象,同時將wrotePostion值增加消息的大小;

1.2.2 消息刷盤操作(commit)
主要功能是將內存中的消息寫入磁盤文件中。方法是commit(final int flushLeastPages)。主要邏輯:
1)檢查文件是否寫滿了,即寫入位置(wrotePostion)是否等於文件大小(fileSize),若已經寫滿則進行刷盤操作;
2)檢查內存中未刷的消息頁數是否大於最小刷盤頁數,即要刷盤的消息頁數flushLeastPages(每頁默認大小爲4K)是否大於【committedPosition(上次刷盤的位置)減去wrotePostion】/4K;若不夠頁數也暫不刷盤;
3)MapedFile的父類是ReferenceResource,該父類的作用是記錄該MapedFile中的內存對象被引用的次數;該引用次數爲正數表示資源可用即未被shutdown,當在刷盤之前將引用次數加1後爲正數,則調用BtyeBuffer的force方法進行刷盤,再將committedPosition置爲wrotePostion值;最後將引用次數減1;若引起次數爲不爲正數則將直接committedPosition置爲wrotePostion值;

1.2.3 隨機讀操作(selectMapedBuffer)
隨機讀操作分爲兩個方法,第一個是讀取指定位置開始的所有消息內容,方法爲:selectMapedBuffer(int pos) ,第二個是讀取指定位置開始的指定消息大小的消息內容,方法爲:selectMapedBuffer(int pos, int size)。
這兩個方法均是調用ByteBuffer的slice和limit方法獲取消息內容,然後初始化SelectMapedBufferResult對象並返回;該對象的startOffset變量是讀取消息的開始位置加上該文件的起始偏移量;

1.2.4 清理內存操作

Cleanup方法主要功能是在調用shutdown時清理掉內存中的二進制信息;

1.2.5 判斷文件是否寫滿

檢查wrotepostion是否等於fileSize,若相等則表示文件已經寫滿;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章