RocketMQ-消息存儲(一):寫入過程

1、當前broker停止工作或爲slave則拒絕寫入;消息主題長度超過256個字符、消息屬性長度超過65536個字符則拒絕該消息寫入

2、如果消息的延遲級別大於0 ,將消息的原主題名稱與原消息隊列 ID 存入消息屬 性中,用延遲消息主題 SCHEDULE TOPIC 、消息隊列 ID 更新原先消息的主題與隊列,這是併發消息消費重試關鍵的一步

3、獲取當前可以寫入的commitLog文件:
Commitlog 文件存儲目錄爲KaTeX parse error: Expected 'EOF', got '}' at position 14: {ROCKET_HOME }̲/ store commitl…{ROCKET_HOME }/store/commitlog 文件夾,而 MappedFile 則對應該文件夾下一個個的文件。

4、在寫入 CornrnitLog 之前,先申請 putMessageLock ,也就是將消息存儲到 CornrnitLog 文件中是串行的

5、設置消息的存儲時間,如果mappedFile 爲空,表明$ {ROCKET_HOME}/store/ commitlog 目錄下不存在任何文件,說明本次消息是第一次消息發送,用偏移量0 創建第 一個 commit 文件,文件爲 00000000000000000000 ,如果文件創建失敗,拋出 CREATE MAPEDFILE FAILED ,很有可能 是磁盤空間不足或權限不夠

6、將消息追加到 MappedFile。 首先先獲取 MappedFile 當前寫指針,如果 currentPos 大於或等於文件大小則表明文件已寫滿,拋出 AppendMessageStatus. UNKNOWN_ ERROR 。如果 currentPos 小於文件大小,通過 slice ()方法創建 個與 MappedFile 的共享內存區,並設置 position 爲當前指針

7、創建全局唯一消息 ID ,消息 ID有 16 字節
但爲了消息 ID 可讀性,返回給應用程序的 msgld 爲字符類型,可以通過 UtilAll. bytes2string 方法將 msgld 字節數組轉換成字符串,通過 Uti1All .stri ng2bytes 方法將 msgld 字符串還原成 16 字節的字節數組,從而根據提取消息偏移量 ,可以快速通過 msgld 找到 消息內容。

8、獲取該消息在消息隊列的偏移量。 CommitLog 中保存了當前所有消息隊列的當 前待寫入偏移量。

9、根據消息體的長度 、主題的長度、屬性的長度結合消息存儲格式計算消息的總長度

10、如果消息長度+END_FILE_ MIN_ BLANK_ LENGTH 大於 CommitLog 文件 的空閒空間,則返回 AppendMessageStatus.END_OF _FILE, Broker 會重新創建一個新的 CommitLog 文件來存儲該消息 從這裏可以看出,每個 CommitLog 文件最少會空閒8個字 節,高 4字節存儲當前文件剩餘空間,低 4字節存儲魔數 CommitLog.BLANK _MAGIC_CODE

11、將消息內容存儲到 ByteBuffer 中,然後創建 AppendMessageResult ,這裏只 是將消息存儲在 MappedFile 對應的內存映射 Buffer 中,並沒有刷寫到磁盤

12、:更新消息隊列邏輯偏移量

13、處理完消息追加邏輯後將釋放 putMessageLock鎖

14、DefaultAppendMessageCallback#doAppend 只是將消息追加在內存中, 需要根 據是同步刷盤還是異步刷盤方式,將內存中的數據持久化到磁盤

發佈了24 篇原創文章 · 獲贊 11 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章