Broker内存映射机制与高效磁盘
RocketMQ在存储涉及中通过内存映射、顺序写文件等方式实现了高吞吐。
RocketMQ的基本数据结构:
CommitLog:RocketMQ对存储消息的物理文件的抽象实现,也就是对物理CommitLog文件的具体实现。MappedFile:CommitLog文件在内存中的映射文件,映射文件同时具有内存的写入速度和与磁盘一样可靠的
持久化方式.
MappedFileQueue:映射文件队列中有全部的CommitLog映射文件,第一个映射文件为最先过期的文件,最后一个文件是最后过期的文件,最新的消息总是写入最后一个映射文件。
每个MappedFileQueue包含多个MappedFile,就是真是的物理CommitLog文件.在Java中通过java.nio.MappedByteBuffer来实现文件的内存映射,即文件读写都是通过MappedByteBuffer(其实是PageCache)来操作的。写入数据时先加锁,然后通过Append方式写入最新MappedFile。对于读取消息,大部分情况下用户只关心最新数据,而这些数据都在PageCache中,也就是说,读写文件就是在PageCache中进行的,其速度几乎等于直接操作内存的速度
Broker文件刷盘机制
消息存储完成后,会被操作系统持久化到磁盘,也就是刷盘。
RocketMQ支持两种刷盘方式,在Broker启动时配置flushDiskType=SYNC_FLUSH表示同步刷盘.配置flushDiskType=ASYNC_FLUSH表示异步刷盘
刷盘涉及以下3个线程服务。如图所示
GroupCommitService
GroupCommitService就是CommitLog.GroupCommitService–同步刷盘任务。在Broker存储消息到PageCache后,在Broker存储消息到PageCache后,同步将PageCache刷到磁盘,在返回客户端消息并写入结果
FlushRealTimeService
FlushRealTimeService就是CommitLog.FlushRealTimeService–异步刷盘服务。在Broker存储消息到PageCache后,立即返回客户端写入结果,然后异步刷盘服务将PageCache异步刷到磁盘
CommitRealTimeService
CommitRealTimeService就是CommitLog.CommitRealTimeService–异步转存服务。Broker通过读写分离将消息写入直接内存(Direct Meomory,简称DM),然后通过异步转存服务,将DM中的数据再次存储到PageCache中,以供异步刷盘服务将PageCache刷到磁盘中,转存服务过程如上
将消息成功保存到CommitLog映射文件后,调用submitFlushRequest()/handleDiskFlush()方法处理刷盘逻辑,
同步刷盘、异步刷盘都是在这个方法中发起的