数据持久化存储,当MQ收到一条消息后,需要向生产者返回一个ACK响应,并将消息存储到磁盘文件。MQ Push一条消息给消费者后,等待消费者的ACK响应,需要将消息标记为已消费。如果没有标记为消费,MQ会不断的尝试往消费者推送这条消息。MQ需要定期删除一些过期的消息,这样才能保证服务一直可用。
一、 RocketMQ消息存储结构
CommitLog:存储消息实体,存储内容为Producer端写入的消息主体内容(消息内容不是定长的)。包含Consume Queues、Message Queue、Tag、Topic、物理地址偏移量等所有信息。所有消息都会顺序存入到CommitLog文件当中,读取是随机读取。CommitLog由多个文件组成,每个文件固定大小1G。超过1g,在写新文件。以第一条消息的偏移量为文件名。多个Topic的消息实体内容都存储于一个CommitLog中,通过索引在分离开。
ConsumerQueue:消息消费队列,存储MessageQueue的消息在CommitLog中的物理地址(文件偏移量)也可以看成是基于topic的CommitLog索引文件。每个MessageQueue都会有对应的ConsumerQueue文件存储在磁盘上。ConsumerQueue文件里每条消息的大小都是20个字节,内容包含启始CommitLog offset(物理偏移量占用8字节)、size(消息大小占用4字节)和MessageTag的HashCode(消息Tag的HashCode值占用8字节)。最多存放30W条数据,文件最大5.72MB,存放满了就新创建一个文件,继续写入。Consumer根据ConsumerQueue查找待消费的消息。
IndexFile:为了消息查询提供了一种通过key或时间区间来查询消息的方法,这种通过IndexFile来查找消息的方法不影响发送与消费消息的主流程。
Broker收到消息的流程:Broker收到一条消息后,先把消息存储在CommitLog中,之后把CommitLog中对应的物理地址(文件偏移量),记录在对应的MessageQueue对应的的ConsumeQueue文件中。
二、刷盘机制
消息写入磁盘方式分为同步刷盘和异步刷盘。同步刷盘在返回写入成功状态的时候数据已经写入到磁盘中。消息写入内存的PAGECACHE后,立刻通知刷盘线程刷盘,等待刷盘成功,刷盘线程唤醒等待线程,返回写入成功状态。异步刷盘在返回写入成功状态时消息被写入了内存的PAGECACHE,当内存PAGECACHE内消息积累到一定程度,触发统一写磁盘操作,这样做可以提高吞吐量,快速写入。刷盘方式通过broker配置文件内的flflushDiskType参数设置&