RocketMQ中的消息存储结构及删除机制
RocketMQ的存储设计
Message
Message是Rocket中很重要的组成部分,也就是消息本身。Message中有messageId,messageKey。message和Topic是多对一的关系,一个主题下边可以有多个消息。
Topic
Topic中有tags和subTopics。每条消息都有对应的Topic,一个Topic下会有多个消息。生产者生产消息的时候会指定Topic,消费者读取消息的时候,会获取指定Topic的消息。
Group
Group,一般会有生产者分组,消费者分组,一个Group可以消费多个Topic,一个Topic也可以被多个Group消费。一般同一个分组的消费者拥有同样的消费行为。
Queue
Queue是队列,也就是存储尚未消费的消息的地方,一般会设置多个,所以一个Topic下边一般会有多个Queue
Offset
Offset是消息偏移量。
消息存储结构
RocketMQ是高可用的,也是因为其对消息等数据进行了持久化存储,对应的存储文件如下所示。
RocketMQ 消息的存储是由 ConsumeQueue 和 CommitLog 配合完成的,消息真正的物理存储文件是 CommitLog,ConsumeQueue 是消息的逻辑队列,类似数据库的索引文件,存储的是指向物理存储的地址。每 个 Topic 下的每个 Message Queue 都有一个对应的ConsumeQueue 文件。
Commitlog
Commitlog是消息存储的目录,所有的消息写入的时候,都会写入到commitlog文件中,并且会存储消息的元数据,也就是消息的Topic,Message,Queueid等信息都会被保存。
CommitLog消息存放的时候,每条消息的前边四个字节存储该消息的总长度。由于消息其他信息长度不固定,所以一个消息的存储长度是不固定的。
每个CommitLog的文件大小为1G,第一个文件的起始偏移量为0,第二个则为1073741824,因为1G=1073741824byte。当写入的时候,会先往同一个文件写,等写满之后,再写入下一个。
CommitLog这样顺序写,会大大的提高写入的效率。
当消息到达Commit文件之后,会有专门的线程产生消息转发任务,从而构建ConsumeQueue文件与Index文件。
ConsumeQueue
消息的逻辑队列,是CommitLog的索引文件,存储的是指向物理存储的地址。每个Topic下的每个MessageQueue都有一个ConsumeQueue文件。在ComsumeQueue文件中,每个节点内包含该消息在Commitlog的偏移量,对应消息的大小,Tag的HashCode。
ConsumeQueue中存储的并不是消息的全量数据,是为了增加查询速度的索引文件。
因为ConsumeQueue的占用内存很小,一般可以全部读入到内存中,这样对ConsumeQueue的操作是极快的。
IndexFile
消息索引文件,当使用messageKey检索消息的时候,就是读取的IndexFile文件,这个文件的存在大大提高了检索消息的速度,是RocketMQ专门为消息订阅构建的索引文件。
Config
Broker配置信息
- topics.json : topic 配置属性,RocketMQ创建了几个topic,每个主题有多少队列,每个队列又是怎么样的,都会存储在这个文件中。
- subscriptionGroup.json :消息消费组配置信息。
- delayOffset.json :延时消息队列拉取进度。
- consumerOffset.json :集群消费模式消息消进度。
- consumerFilter.json :主题消息过滤信息。
其他文件
abort
记录Broker是否正常关闭,这是一个空文件,当Broker正常关闭的时候,会删除abort文件。但是当异常宕机或其他原因关闭的时候,则不做删除处理。
checkpoint
文件检查点,记录Commit最后一次刷盘的时间,consumequeue最后一次刷盘时间,index索引文件最后一次刷盘时间
消息删除机制
为了避免内存与磁盘的浪费,RocketMQ有专门的删除机制来删除过期的文件。
消息消费队列文件与消息存储文件( Commitlog )共用一套过期文件机制。
清理的逻辑是:如果非当前写文件在一定时间间隔内没有再次被更新,则认为是过期文件,可以被删除, RocketMQ 不会关注这个文件上的消息是否全部被消费。
通过在 Broker配置文件中设置 fileReservedTime 来改变过期时间,默认为48,单位为小时。
触发文件清除操作的是一个定时任务,而且只有定时任务可以执行这个操作,默认每 10s 执行一次。
过期判断
fileReservedTime是允许文件保留的最长时间,当文件最后一次更新的时间到现在的时间超过这个时间了。那么这个文件将被删除。
还有两个参数:
-
deletePhysicFilesInterval:删除间隔默认100ms,若是有多个文件同时过期,并不会同时删除多个文件,而是间隔deletePhysicFilesInterval时间后继续删除。
-
destroyMapedFileIntervalForcibly:当删除某个文件的时候,若是该文件还在被引用,将阻止删除操作。destroyMapedFileIntervalForcibly则表示当第一次删除拒绝之后,删除免疫的时间,在这个时间内将一直拒绝删除,超过这个时间之后,则可以被删除。
删除条件
指定时间删除
可以通过deleteWhen设置一天执行一次删除文件的操作,默认是凌晨4点。
磁盘满删除
DiskSpaceCleanForciblyRatio参数是磁盘占用的阈值。
检查磁盘是否充足,若是磁盘占用超过百分之85(默认),则会触发过期文件删除操作。
#java#