RocketMQ 消息持久化机制
我們知道 RocketMQ 是一款高性能、高可靠的分布式消息中間件,高性能和高可靠是很難兼得的。因為要保證高可靠,那么數據就必須持久化到磁盤上,將數據持久化到磁盤,那么可能就不能保證高性能了。
RocketMQ 在兼容這兩方面做的不錯,先從磁盤說起,「現代的磁盤都是高性能的,寫速度并不一定比網絡的數據傳輸速度慢」。比如 SSD 固態硬盤在 M.2 NVMe協議下,順序寫的速度可以達到 1500 MB/s,就算是普通磁盤,如果性能比較高的話,順序寫的速度可以達到 450MB/s~600MB/s。
在順序寫的情況下是這速度,但是不人為控制的話,磁盤采用的是隨機寫,在隨機寫的情況下,磁盤的寫入速度急速下降,「磁盤的隨機寫速度可能只有幾百KB/s,這遠遠要慢于網絡傳輸速度,所以它并不能滿足高性能的要求」。
RocketMQ 在持久化的設計上,采取的是「消息順序寫、隨機讀的策略」,利用磁盤順序寫的速度,讓磁盤的寫速度不會成為系統的瓶頸。并且采用 MMPP 這種“零拷貝”技術,提高消息存盤和網絡發送的速度。極力滿足 RocketMQ 的高性能、高可靠要求。
在 RocketMQ 持久化機制中,涉及到了三個角色:
- 「CommitLog」:消息真正的存儲文件,所有消息都存儲在 CommitLog 文件中。
- 「ConsumeQueue」:消息消費邏輯隊列,類似數據庫的索引文件。
- 「IndexFile」:消息索引文件,主要存儲消息 Key 與 offset 對應關系,提升消息檢索速度。
生產者將消息發送到 RocketMQ 的 Broker 后,Broker 服務器會將「消息順序寫入到 CommitLog 文件中」,這也就是 RocketMQ 高性能的原因,因為我們知道磁盤順序寫特別快,RocketMQ 充分利用了這一點,極大的提高消息寫入效率。
但是消費者消費消息的時候,可能就會遇到麻煩,每一個消費者只能訂閱一個主題,消費者關心的是訂閱主題下的所有消息,但是同一主題的消息在 CommitLog 文件中可能是不連續的,那么「消費者消費消息的時候,需要將 CommitLog 文件加載到內存中遍歷查找訂閱主題下的消息,頻繁的 IO 操作,性能就會急速下降」。
為了解決這個問題,RocketMQ 引入了 Consumequeue 文件。「Consumequeue 文件可以看作是索引文件,類似于 MySQL 中的二級索引」。在存放了同一主題下的所有消息,消費者消費的時候只需要去對應的 Consumequeue 組中取消息即可。
「IndexFile」?是 RocketMQ 為消息訂閱構建的索引文件,用來提高根據主題與消息隊列檢索消息的速度
因為操作系統 PAGECACHE 的存在,PageCache是OS對文件的緩存,用于加速對文件的讀寫,所以一般都是先寫入到 PAGECACHE 中,然后再持久化到磁盤上。我們熟悉的其他組件,MySQL、Redis 等都是如此。RocketMQ 也不列外。
在 RocketMQ 中提供了「同步刷盤」和「異步刷盤」兩種刷盤方式,可以通過 Broker 配置文中中的 flushDiskType 參數來設置(SYNC_FLUSH、ASYNC_FLUSH)。
「異步刷盤方式(默認)」:消息寫入到內存的 PAGECACHE中,就立刻給客戶端返回寫操作成功,當 PAGECACHE 中的消息積累到一定的量時,觸發一次寫操作,將 PAGECACHE 中的消息寫入到磁盤中。這種方式「吞吐量大,性能高,但是 PAGECACHE 中的數據可能丟失,不能保證數據絕對的安全」。
「同步刷盤方式」:消息寫入內存的 PAGECACHE 后,立刻通知刷盤線程刷盤,然后等待刷盤完成,刷盤線程執行完成后喚醒等待的線程,返回消息寫成功的狀態。這種方式「可以保證數據絕對安全,但是吞吐量不大」。
?
總結
以上是生活随笔為你收集整理的RocketMQ 消息持久化机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库调优
- 下一篇: 单例模式的5种实现方法及优缺点