RocketMQ的消息存储是主要离不开CommitLog和ConsumerQueue这两个文件,他们相互配合完成数据的存储和读取。如下图所示:
CommitLog 消息存储物理文件
从上图可以看出有两个非常重要的文件:CommitLog和ConsumerQueue。CommitLog是消息存储的日志数据文件,Producer 发送消息最终顺序写入到此文件中,并且CommitLog文件采用混合型存储(当前broker的所有Topic 下的消息队列共用同一个 CommitLog 的日志数据文件),并通过建立消息逻辑队列-ConsumeQueue 的方式来区分不同 Topic 下面的不同 MessageQueue 的消息,每个Topic下的每个MessageQueue都有一个对应的ConsumeQueue文件。
ConsumerQueue 消息逻辑队列
ConsumerQueue相当于字典的目录,起导索引文件的作用,用来指定消息在消息物理文件CommitLog上的位置。同时为消费消息起到一定的缓冲作用(只有 ReputMessageService 异步服务线程通过 doDispatch 异步生成了 ConsumeQueue 队列的元素后,Consumer才能进行消费)。这样,只要消息写入并刷盘至 CommitLog 文件后,消息就不会丢失,即使 ConsumeQueue 中的数据丢失,也可以通过 CommitLog 来恢复。
ConsumeQueue中存储单元是一个20字节定长的二进制数据,顺序写顺序读。
- CommitLog Offset:指这条消息在CommitLog文件中的实际偏移量,用此可以直接查找到CommitLog中消息
- Size:存储消息的大小
- Message Tag HashCode:存储消息的Tag的哈希值:主要用于订阅时消息过滤(订阅时如果指定了Tag,会根据HashCode来快速查找到订阅的消息)。用途在于,如果一个topic下有多重业务消息,那生产者可以通过设置Tag标签来进行消息的分类,消费者可以通过Tag来过滤出需要的类型消息。
ConsumeQueue存储的目录结构如下:
- 一个Topic一个文件夹
- 在一个Topic文件夹下,一个MessageQueue一个文件夹,使用0-n来命名
- 一个MessageQueue文件夹里有多个文件,每个5.7m左右,用来存储属于当前MessageQueue消息的位置信息
IndexFile 消息索引文件
ConsumerQueue是通过偏移量offset去CommitLog文件中查找消息,但实际工作应用中,我们想查找某条具体的消息,并不知道offset值,那该怎么办呢?那IndexFile作用就来了。
IndexFile是消息索引文件,如果一个生产者发送的消息包含key值的话,会使用IndexFile存储消息索引,主要用于使用key来查询消息。文件的内容结构如图:
在Broker端&#x