RocketMQ主要存储的文件包括Comitlog文件、ConsumeQueue文件、IndexFile文件,存储路径为${ROCKET_HOME}/store
,默认在当前用户目录下的store目录:
store目录下的文件如上所示,分别有:checkpoint、commitlog、config、consumequeue、index、lock,下面一一介绍一下RocketMQ主要的存储文件夹:
进入RocketMQ存储剖析之前,先看一下RocketMQ数据流向,如图所示:
生产者推将消息推送给对应的Broker之后,Broker会将消息内容持久化到对应的commitLog文件,然后ReputMessageService线程会定时以CommitLog文件为基础来更新ConsumeQueue文件和index文件;作为消费者,会根据ConsumeQueue的offset信息,拉取对应queue的数据消费,所以,当消息生产者提交的消息存储在Commitlog文件中,ConsumeQueue、IndexFile需要及时更新,否则消息无法及时被消费
基于上面的介绍,我们大致了解到了RocketMQ整个存储设计所关联到的文件结构以及文件的数据流向,下面我们再来介绍核心数据文件的内容结构以及每个文件所承担的核心能力,而对于具体的源码实现,博主会放到后续文章,正在排版中,感兴趣的朋友可关注一下,后续会持续更新RocketMq的相关内容。
CommitLog文件的消息组织格式如下:
每条消息的前四个字节存储该消息的总长度,然后是固定长度的其它属性,RocketMq其它属性因涉及种类比较多,将近20种属性类型,此处只简单介绍下一些核心属性:
在RocketMq的实现中,commitlog对应的数据结构为org.apache.rocketmq.store.CommitLog,其提供的核心能力有:
到这里,我们已经知道,RoceketMq会将所有消息存储在commitlog目录下面,虽说目录下面会分文件,但是一个Broker实例有多少个Topic,每个Topic下面会有多少条消息我们也不知道,所以为了加快消息检索速度,RocketMq设计了消息消费队列文件(Consumequeue),该文件可以看成是Commitlog关于消息消费的“索引”文件,consumequeue的第一级目录为消息主题,第二级目录为主题的消息队列,如下所示:
为了加速ConsumeQueue消息条目的检索速度与节省磁盘空间,每一个Consumequeue条目不会存储消息的全量信息,其存储格式如下:
RocketMQ的index又称之为Hash索引,其主要是为消息建立索引机制,既然是Hash索引,那必然存在Hash槽和Hash冲突问题,下面我们先看下RocketMQ的Hash索引的文件结构,然后再讲述RocketMQ是怎么解决Hash冲突的:
从图中可以看出,IndexFile总共包含IndexHeader、Hash槽、Hash条目(数据):
对于RocketMQ如何解决Hash冲突关键点在于Hash槽中存储的是该HashCode所对应的最新的Index条目的下标,新的Index条目的最后4个字节存储该HashCode上一个条目的Index下标,至于Hash冲突解决的详细实现以及Index文件数据写入过程,此处,博主这里不再详细介绍,具体的实现在后续的源码实现章节再详细介绍org.apache.rocketmq.store.index.IndexFile#putKey
整个代码实现,其实并不难,就跟通常解决Hash冲突的办法类似相同
checkpoint的作用是记录Comitlog、ConsumeQueue、Index文件的刷盘时间点,文件固定长度为4k,其中只用该文件的前面24个字节,其存储格式如图所示:
RocketMQ是一款高性能的消息中间件,存储部分的设计是核心,存储的核心是IO访问性能,基于对于RocketMQ的兴趣,博主后续会将整个学习过程,不断记录,感兴趣的朋友可关注留下评论,一起学习RocketMQ整个优秀的设计,下图是串联整个消息的存储过程,因涉及到知识点比较多,还在不断细化中