目录
1.RocketMQ消息存储结构
RocketMQ支持消息的持久化,所以对消息可以基于文件进行存储。
1.1 存储文件
- commitLog:消息存储的目录。
- config:运行期间的一些配置信息。
- consumequeue:消息队列的存储目录。
- index:消息索引文件存储目录。
- abort:RocketMQ的Broker非正常关闭产生的错误文件。
- checkpoint:文件检查点,存储commitLog文件最后一次刷盘的时间、consumerqueue最后一次刷盘时间等等。
1.2 消息的存储结构
1.2.1 CommitLog
CommitLog是以物理文件的方式进行存放,每一台Broker节点上的CommitLog被所有的ConsumerQueue共享。在CommitLog中,每一个消息的长度是不固定的。CommitLog里面不同Topic消息通过磁盘顺序写进行存储。
CommitLog文件大小默认是1GB,也可以支持配置。每台Broker只会往一个CommitLog文件中顺序写,写完一个接着写另一个。
IndexFile和ConsumerQueue都有消息对应的物理偏移量,通过偏移量就可以得到消息的具体在哪个CommitLog中的位置。
CommitLog的特点是:顺序写,随机读。
1.2.2 ConsumeQueue
ConsumeQueue是消息的逻辑队列,存储的是指向物理存储文件的地址。每一个Topic下的每一个Message Queue都有一个对应的ConsumeQueue文件。例如某一个Topic在Broker上有4个MessageQueue,那么这个Topic就会有4个ConsumeQueue文件。
每个ConsumeQueue中存储的消息条目都不是全量数据,而是消息的一部分信息,包括消息在CommitLog中的偏移量、消息大小、消息Tag的哈希值。
当消息存储到CommitLog中后,由后台消息负责构建ConsumeQueue。
单个ConsumeQueue文件最大存储30万个条目。
1.2.3 IndexFile
IndexFile的作用就是提高RocketMQ检索查询消息而设计,RocketMQ支持通过MessageID、MessageKey来查询消息。IndexFile是一个索引文件,底层通过500万个hash槽和冲突链表实现,来做定位查询,一个IndexFile最多2000w条数据。当超过这个数量后就会新建IndexFile。
2.过期文件删除机制
RocketMQ操作CommitLog、ConsumeQueue是基于内存映射MMAP技术实现的,在Broker启动的时候就会加载这两个目录下的所有文件,所以不可能消息永久性的保存在服务器上。
RocketMQ清除过期文件的方法是:如果某个文件在一定间隔时间内没有被更新,则认为是过期的文件,可以被删除,默认每个文件的过期时间是72小时,可以配置。
RocketMQ触发删除文件的点有:
- 指定删除文件的时间点,默认是凌晨4点。
- 发现磁盘空间不足或达到阈值会触发。
- 手动触发。
3.RocketMQ对MMap的应用
RocketMQ为了提高文件传输的效率采用了mmap技术来实现零拷贝。CommitLog、ConsumeQueue都是通过内存文件映射进行操作。因为使用MappedByteBuffer这种实现有物理大小1.5G~2G的限制,所以单个CommitLog文件大小默认是1GB。