刷助力源码
Ⅰ 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 进行刷盘。