RocketMQ DLedger 的存儲實作思路與 RocketMQ 的存儲實作思路相似,本文就不再從源碼角度詳細剖析其實作,隻是點出其實作關鍵點。我們不妨簡單回顧一下 CommitLog 檔案、ConsumeQueue 檔案設計思想。
其檔案組成形式如下:
正如上圖所示,多個 commitlog 檔案組成一個邏輯上的連續檔案,使用 MappedFileQueue 表示,單個 commitlog 檔案使用 MappedFile 表示。溫馨提示:如果想詳細了解 RocketMQ 關于存儲部分的講解,可以關注筆者的《RocketMQ 技術内幕》一書。
1、DLedger 存儲相關類圖
1.1 DLedgerStore
存儲抽象類,定義如下核心方法:
-
public abstract DLedgerEntry appendAsLeader(DLedgerEntry entry)
向主節點追加日志(資料)。
-
public abstract DLedgerEntry appendAsFollower(DLedgerEntry entry, long leaderTerm, String leaderId)
向從節點同步日志。
-
public abstract DLedgerEntry get(Long index)
根據日志下标查找日志。
-
public abstract long getCommittedIndex()
擷取已送出的下标。
-
public abstract long getLedgerEndTerm()
擷取 Leader 目前最大的投票輪次。
-
public abstract long getLedgerEndIndex()
擷取 Leader 下一條日志寫入的下标(最新日志的下标)。
-
public abstract long getLedgerBeginIndex()
擷取 Leader 第一條消息的下标。
-
public void updateCommittedIndex(long term, long committedIndex)
更新commitedIndex的值,為空實作,由具體的存儲子類實作。
-
protected void updateLedgerEndIndexAndTerm()
更新 Leader 維護的 ledgerEndIndex 和 ledgerEndTerm 。
-
public void flush()
刷寫,空方法,由具體子類實作。
-
public long truncate(DLedgerEntry entry, long leaderTerm, String leaderId)
删除日志,空方法,由具體子類實作。
-
public void startup()
啟動存儲管理器,空方法,由具體子類實作。
-
public void shutdown()
關閉存儲管理器,空方法,由具體子類實作。
1.2 DLedgerMemoryStore
Dledger 基于記憶體實作的日志存儲。
1.3 DLedgerMmapFileStore
基于檔案記憶體映射機制的存儲實作。其核心屬性如下:
-
long ledgerBeginIndex = -1
日志的起始索引,預設為 -1。
l- ong ledgerEndIndex = -1
下一條日志下标,預設為 -1。
-
long committedIndex = -1
已送出的日志索引。
-
long ledgerEndTerm
目前最大的投票輪次。
-
DLedgerConfig dLedgerConfig
DLedger 的配置資訊。
-
MemberState memberState
狀态機。
-
MmapFileList dataFileList
日志檔案(資料檔案)的記憶體映射Queue。
-
MmapFileList indexFileList
索引檔案的記憶體映射檔案集合。(可對标 RocketMQ MappedFIleQueue )。
-
ThreadLocal< ByteBuffer> localIndexBuffer
本地線程變量,用來緩存索引ByteBuffer。
-
ThreadLocal< ByteBuffer> localEntryBuffer
本地線程變量,用來緩存資料索引ByteBuffer。
-
FlushDataService flushDataService
資料檔案刷盤線程。
-
CleanSpaceService cleanSpaceService
清除過期日志檔案線程。
-
boolean isDiskFull = false
磁盤是否已滿。
-
long lastCheckPointTimeMs
上一次檢測點(時間戳)。
-
AtomicBoolean hasLoaded
是否已經加載,主要用來避免重複加載(初始化)日志檔案。
-
AtomicBoolean hasRecovered
是否已恢複。
2、DLedger 存儲 對标 RocketMQ 存儲
存儲部分主要包含存儲映射檔案、消息存儲格式、刷盤、檔案加載與檔案恢複、過期檔案删除等,由于這些内容在 RocketMQ 存儲部分都已詳細介紹,故本文點到為止,其對應的參考映射如下:
在 RocketMQ 中使用 MappedFile 來表示一個實體檔案,而在 DLedger 中使用 DefaultMmapFIle 來表示一個實體檔案。
在 RocketMQ 中使用 MappedFile 來表示多個實體檔案(邏輯上連續),而在 DLedger 中則使用MmapFileList。
在 RocketMQ 中使用 DefaultMessageStore 來封裝存儲邏輯,而在 DLedger 中則使用DLedgerMmapFileStore來封裝存儲邏輯。
在 RocketMQ 中使用 Commitlog$FlushCommitLogService 來實作 commitlog 檔案的刷盤,而在 DLedger 中則使用DLedgerMmapFileStore$FlushDataService來實作檔案刷盤。
在 RocketMQ 中使用 DefaultMessageStore$CleanCommitlogService 來實作 commitlog 過期檔案的删除,而 DLedger 中則使用 DLedgerMmapFileStore$CleanSpaceService來實作。
由于其實作原理相同,上述部分已經在《RocketMQ 技術内幕》第4章中詳細剖析,故這裡就不重複分析了。
3、DLedger 資料存儲格式
存儲格式字段的含義如下:
-
magic
魔數,4位元組。
-
size
條目總長度,包含 Header(協定頭) + 消息體,占4位元組。
-
entryIndex
目前條目的 index,占8位元組。
-
entryTerm
目前條目所屬的 投票輪次,占8位元組。
-
pos
該條目的實體偏移量,類似于 commitlog 檔案的實體偏移量,占8位元組。
-
channel
保留字段,目前版本未使用,占4位元組。
-
chain crc
目前版本未使用,占4位元組。
- body crc
- 的 CRC 校驗和,用來區分資料是否損壞,占4位元組。
-
body size
用來存儲 body 的長度,占4個位元組。
-
body
具體消息的内容。
源碼參考點:DLedgerMmapFileStore#recover、DLedgerEntry、DLedgerEntryCoder。
4、DLedger 索引存儲格式
即一個索引條目占32個位元組。
5、思考
DLedger 存儲相關就介紹到這裡,為了與大家增加互動,特提出如下兩個思考題,歡迎與作者互動,這些問題将在該系列的後面文章專題探讨。
1、DLedger 如果整合 RocketMQ 中的 commitlog 檔案,使之支援多副本?
2、從老版本如何更新到新版本,需要考慮哪些因素呢?
原文釋出時間為:2019-09-01
本文作者:丁威,《RocketMQ技術内幕》作者。
本文來自
中間件興趣圈,了解相關資訊可以關注
。