RocketMQ的消息存储在本地文件系统中,这些相关文件默认在当前用户主目录下的store目录中。store目录中主要有以下文件夹:
- commitLog:存放commitlog文件,消息是写在commitlog文件中的
- checkpoint:存储commitLog,consumequeue,index文件的最后刷盘时间戳
- abort:该文件在broker启动后会自动创建,正常关闭broker,该文件会自动消失。如若在没有启动broker的情况下发现该文件存在,说明之前的broker关闭是非正常关闭的
- config:存放broker运行期间的一些配置数据
- consumequeue:存放consumequeue文件,队列就存放在这个目录中
- index:存放消息索引文件indexFile
- lock:运行期间使用的全局资源锁
1、commitLog(mappedFile)文件
- 目录与文件
commitLog文件夹立存放着很多mappedFile文件,当前所有broker中的消息都要落盘到这些mappedFile文件。mappedFile的文件大小时是1G(最大值),文件名由20位的十进制数构成,表示当前文件的第一条消息的起始位移偏移量。
需要注意的是,一个broker中仅包含一个commitLog目录,所有的mappedFile文件都是存放在该目录。也即无论当前broker存放多少个Topic消息,都顺序写入到mappeFile文件中,并没有按照Topic分类。
- 消息单元
mappedFile文件内容由一个个的消息单元组成。每个消息单元都包括MsgLen、消息的物理位置physicalOffset、消息体内容body、消息体长度BodyLength、消息主题Topic,Topic长度TopicLength、消息生产者BornHost、消息发送时间戳BornTimestamp、消息所在的队列QueuId、消息在Queue中存储的便宜了QueueOffset等近20多项消息属性
2、consumequeue
- 目录与文件
为了提高效率,会在~/store/comsumequeue中创建一个目录,目录名称是Topic名称。在该目录下,会再为每个该Topic的Queue创建一个目录,目录名是queueId.每个目录中存放着若干consumequeue文件,该文件是commitlog的索引文件,可以根据consumequeue定位到具体的消息。
consumequeue文件名也是20位数字构成,表示当前文件的第一个索引条目的起始位置偏移量。与mappedFile文件不同的是。其后续文件名是固定的,因为consumequeue文件大小是固定的。
- 索引条目
每个consumequeue文件可以包含30w个索引目录,每条索引目录都包含上图三个属性,这三个属性占20个字节,所以每个文件的大小都是30w*20字节
3、对文件的读写
消息写入
- broker根据queueId,获取到该消息对应索引条目要在consumequeue目录中的写入偏移量,即QueueOffset
- 将queueId,queueOffset等数据,与消息一起封装成消息单元
- 将消息单元写入到commitlog,形成消息索引条目
- 将消息索引条目分发到相应的consumequeue
消息拉取
当consumer拉取信息时会经历以下几个步骤:
- consumer获取到要消费的消息所在Queue的消费偏移量offset(消费进度),计算出要消费的消息offset(消费offset+1)
- consumer向broker发送拉取请求,其中会包含其要拉取的消息queue,offset以及消息tag
- broker计算在该consumequeue中的queueOffset
- 从该queueOffset处开始向后查找第一个指定tag的索引条目
- 解析该索引条目的前8个字节,即可定位到该消息在commitlog中的offset
- 从对应的commitlog offset中读取消息单元,并发送给consumer