刷助力源碼
Ⅰ RocketMQ源碼-同步和非同步刷盤
1 概述
2 相關類介紹
3 同步刷盤原理
4 非同步刷盤
RocketMQ和其他存儲系統類似,如Redis等,提供了同步和非同步兩種刷盤方式,同步刷盤方式能夠保證數據被寫入硬碟,做到真正的持久化,但是也會讓系統的寫入速度受制於磁碟的IO速度;而非同步刷盤方式在將數據寫入緩沖之後就返回,提供了系統的IO速度,卻存在系統發生故障時未來得及寫入硬碟的數據丟失的風險。
RocketMQ提供了 SYNC_FLUSH 和 ASYNC_FLUSH 兩種方式,也即同步和非同步刷盤方式,同步刷盤在寫入消息後會等待刷盤進度大於等於當前寫入經度之後返回,而非同步刷盤則在寫入消息之後直接返回,不再等待刷盤進度。
在閱讀本文前可先看文章 RocketMQ源碼-MappedFile介紹 ,了解其中介紹的暫存池相關原理以及具體刷盤操作時 commit 和 flush 動作的區別,本文在介紹刷盤時則不再贅述。
其實同步刷盤、非同步刷盤和我們在文章 RocketMQ源碼-主從同步復制和非同步復制 介紹的同步復制、非同步復制原理基本相同,同步刷盤也是阻塞等待當前刷盤進度大於等於此次寫入進度然後返回,而非同步刷盤寫入之後直接返回,由後台線程定時進行刷盤動作。
如果配置的刷盤方式為同步方式,即 SYNC_FLUSH ,那麼根據我們在文章 RocketMQ源碼-MappedFile介紹 第8節介紹的注意事項可知,該配置肯定不會啟用 MappedFile 的暫存池 TransientStorePool 功能。而 GroupCommitService 就是用於同步刷盤時進行實際的刷盤動作。
用於沒有啟用暫存池的非同步刷盤動作,主要是定時觸發 flush 動作。
用於啟用了暫存池的非同步刷盤動作,和 FlushRealTimeService 不同的是, CommitRealTimeService 在刷盤時會先將從暫存池借用的 ByteBuffer 中的數據 commit 到 fileChannel 中,然後調用 flush 對 fileChannel 進行刷盤操作。
CommitLog.putMessage 在寫入消息之後,會調用 handleDiskFlush 進行刷盤相關處理,該方法實現如下:
相關的服務源碼比較簡單,和主從同步復制及其類似,這里不再介紹,建議閱讀文章 RocketMQ源碼-主從同步復制和非同步復制 做對比理解。
非同步刷盤則寫入消息之後直接返回,由 ServiceThread 實現類 FlushRealTimeService 以及 CommitRealTimeService 在後台根據配置的刷盤頻率進行非同步刷盤, FlushRealTimeService 對未啟用暫存池的 MappedFile 進行刷盤,而 CommitRealTimeService 則對啟用了暫存池的 MappedFile 進行刷盤。