探秘 RocketMQ 消息持久化機制

我們知道 RocketMQ 是一款高性能、高可靠的分散式消息中間件,高性能和高可靠是很難兼得的。因為要保證高可靠,那麼數據就必須持久化到磁碟上,將數據持久化到磁碟,那麼可能就不能保證高性能了。

RocketMQ 在兼容這兩方面做的不錯,先從磁碟說起,現代的磁碟都是高性能的,寫速度並不一定比網路的數據傳輸速度慢。比如 SSD 固態硬碟在 M.2 NVMe協議下,順序寫的速度可以達到 1500 MB/s,就算是普通磁碟,如果性能比較高的話,順序寫的速度可以達到 450MB/s~600MB/s。

在順序寫的情況下是這速度,但是不人為控制的話,磁碟採用的是隨機寫,在隨機寫的情況下,磁碟的寫入速度急速下降,磁碟的隨機寫速度可能只有幾百KB/s,這遠遠要慢於網路傳輸速度,所以它並不能滿足高性能的要求

RocketMQ 在持久化的設計上,採取的是消息順序寫、隨機讀的策略,利用磁碟順序寫的速度,讓磁碟的寫速度不會成為系統的瓶頸。並且採用 MMPP 這種「零拷貝」技術,提高消息存檔和網路發送的速度。極力滿足 RocketMQ 的高性能、高可靠要求。

上述從硬體的角度聊聊了高性能的保證,這些咱也不懂,還是來看看 RocketMQ 持久化機制的架構圖吧。

RocketMQ 存儲核心架構

在 RocketMQ 持久化機制中,涉及到了三個角色:

  • CommitLog:消息真正的存儲文件,所有消息都存儲在 CommitLog 文件中。
  • ConsumeQueue:消息消費邏輯隊列,類似資料庫的索引文件。
  • IndexFile:消息索引文件,主要存儲消息 Key 與 offset 對應關係,提升消息檢索速度。

咱們逐一聊聊吧,CommitLog 文件是存放消息數據的地方,所有的消息都將存入到 CommitLog 文件中。生產者將消息發送到 RocketMQ 的 Broker 後,Broker 伺服器會將消息順序寫入到 CommitLog 文件中,這也就是 RocketMQ 高性能的原因,因為我們知道磁碟順序寫特別快,RocketMQ 充分利用了這一點,極大的提高消息寫入效率。

但是消費者消費消息的時候,可能就會遇到麻煩,每一個消費者只能訂閱一個主題,消費者關心的是訂閱主題下的所有消息,但是同一主題的消息在 CommitLog 文件中可能是不連續的,那麼消費者消費消息的時候,需要將 CommitLog 文件載入到記憶體中遍歷查找訂閱主題下的消息,頻繁的 IO 操作,性能就會急速下降

為了解決這個問題,RocketMQ 引入了 Consumequeue 文件。Consumequeue 文件可以看作是索引文件,類似於 MySQL 中的二級索引。在存放了同一主題下的所有消息,消費者消費的時候只需要去對應的 Consumequeue 組中取消息即可。Consumequeue 文件不會存儲消息的全量資訊,了解 MySQL 索引的話,應該好理解這裡,具體存儲的欄位,我在上圖已經標註。這樣做可以帶來以下兩個好處:

  • 由於 Consumequeue 文件內容小,可以儘可能的保證 Consumequeue 文件全部讀入到記憶體,提高消費效率。
  • Consumequeue 文件也是會持久化的,不存全量資訊可以節約磁碟空間。

IndexFile 是 RocketMQ 為消息訂閱構建的索引文件,用來提高根據主題與消息隊列檢索消息的速度,這個就不細說了。

RocketMQ 持久化機制原理差不多就這些了,接下來聊一聊消息數據刷盤吧。

因為作業系統 PAGECACHE 的存在,PageCache是OS對文件的快取,用於加速對文件的讀寫,所以一般都是先寫入到 PAGECACHE 中,然後再持久化到磁碟上。我們熟悉的其他組件,MySQL、Redis 等都是如此。RocketMQ 也不列外。

在 RocketMQ 中提供了同步刷盤非同步刷盤兩種刷盤方式,可以通過 Broker 配置文中中的 flushDiskType 參數來設置(SYNC_FLUSH、ASYNC_FLUSH)。

刷盤策略

非同步刷盤方式(默認):消息寫入到記憶體的 PAGECACHE中,就立刻給客戶端返回寫操作成功,當 PAGECACHE 中的消息積累到一定的量時,觸發一次寫操作,將 PAGECACHE 中的消息寫入到磁碟中。這種方式吞吐量大,性能高,但是 PAGECACHE 中的數據可能丟失,不能保證數據絕對的安全

同步刷盤方式:消息寫入記憶體的 PAGECACHE 後,立刻通知刷盤執行緒刷盤,然後等待刷盤完成,刷盤執行緒執行完成後喚醒等待的執行緒,返回消息寫成功的狀態。這種方式可以保證數據絕對安全,但是吞吐量不大

關於RocketMQ 持久化機制的分享就這些,感謝您的閱讀,希望這篇文章對您的學習或者工作有一點幫助。有收穫的話,也可以幫忙推薦給其他的小夥伴,讓更多的人受益,萬分感謝

歡迎關注公眾號【互聯網平頭哥】。這裡有職場感悟、Java 技術,雖然不高大上,但通俗易懂。今天最好的是明天最低的要求,願你我共同進步。

互聯網平頭哥