源碼分析 RocketMQ DLedger 多副本存儲實現

RocketMQ DLedger 的存儲實現思路與 RocketMQ 的存儲實現思路類似,本文就再也不從源碼角度詳細剖析其實現,只是點出其實現關鍵點。咱們不妨簡單回顧一下 CommitLog 文件、ConsumeQueue 文件設計思想。緩存

其文件組成形式以下: 在這裏插入圖片描述app

正如上圖所示,多個 commitlog 文件組成一個邏輯上的連續文件,使用 MappedFileQueue 表示,單個 commitlog 文件使用 MappedFile 表示。線程

> 舒適提示:若是想詳細瞭解 RocketMQ 關於存儲部分的講解,能夠關注筆者的《RocketMQ 技術內幕》一書。設計

一、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

基於文件內存映射機制的存儲實現。其核心屬性以下:blog

  • 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 是否已恢復。

二、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章中詳細剖析,故這裏就不重複分析了。

三、DLedger 數據存儲格式

在這裏插入圖片描述

存儲格式字段的含義以下:

  • magic 魔數,4字節。
  • size 條目總長度,包含 Header(協議頭) + 消息體,佔4字節。
  • entryIndex 當前條目的 index,佔8字節。
  • entryTerm 當前條目所屬的 投票輪次,佔8字節。
  • pos 該條目的物理偏移量,相似於 commitlog 文件的物理偏移量,佔8字節。
  • channel 保留字段,當前版本未使用,佔4字節。
  • chain crc 當前版本未使用,佔4字節。
  • body crc body 的 CRC 校驗和,用來區分數據是否損壞,佔4字節。
  • body size 用來存儲 body 的長度,佔4個字節。
  • body 具體消息的內容。

源碼參考點:DLedgerMmapFileStore#recover、DLedgerEntry、DLedgerEntryCoder。

四、DLedger 索引存儲格式

在這裏插入圖片描述

即一個索引條目佔32個字節。

五、思考

DLedger 存儲相關就介紹到這裏,爲了與你們增長互動,特提出以下兩個思考題,歡迎與做者互動,這些問題將在該系列的後面文章專題探討。

一、DLedger 若是整合 RocketMQ 中的 commitlog 文件,使之支持多副本? 二、從老版本如何升級到新版本,須要考慮哪些因素呢?

尊敬的讀者朋友們,都閱讀到這裏了,麻煩幫忙點個贊鼓勵一下我,謝謝。


> 做者簡介:《RocketMQ技術內幕》做者,RocketMQ 社區佈道師,維護公衆號:中間件興趣圈,可掃描以下二維碼與做者進行互動。

相關文章
相關標籤/搜索