文章目录
版本
- 基于
rocketmq-all-4.3.1
版本
ConsumeQueue
-
每个
ConsumeQueue
都有一个queueId,queueId 的值为0到TopicConfig配置的队列数量。比如某个Topic的消费队列数量为4,那么四个ConsumeQueue
的queueId就分别为0、1、2、3。 -
ConsumerQueue
相当于CommitLog
的索引文件,消费者消费时会先从ConsumerQueue
中查找消息在CommitLog
中的offset,再去CommitLog中找原始消息数据。如果某个消息只在CommitLog
中有数据,没在ConsumerQueue
中, 则消费者无法消费 -
Consumequeue
类对应的是每个topic和queuId下面的所有文件.默认存储路径是**$HOME/store/consumequeue/{topic}/{queueId}/{fileName},每个文件由30w条数据组成,单个文件的大小是30w x 20Byte** -
每一个ConsumeQueue存储的格式为
commitLogOffset(8B)+size(4B)+tagHashCode(8B)
,总共20B。存tag是为了在Consumer取到消息offset后先根据tag做一次过滤,剩下的才需要到CommitLog
中取消息详情 -
ConsumeQueue核心属性
public class ConsumeQueue { private final DefaultMessageStore defaultMessageStore; //映射文件队列,管理ConsumeQueue private final MappedFileQueue mappedFileQueue; // 消息topic private final String topic; // 消息队列Id private final int queueId; //指定大小的缓冲,记录的大小是20byte的固定大小 private final ByteBuffer byteBufferIndex; //保存的路径 private final String storePath; //映射文件的大小 private final int mappedFileSize; //最后一个消息对应的物理偏移量 也就是在CommitLog中的偏移量 private long maxPhysicOffset = -1; //最小的逻辑偏移量 在ConsumeQueue中的最小偏移量 private volatile long minLogicOffset = 0; //ConsumeQueue的扩展文件 private ConsumeQueueExt consumeQueueExt = null; }
-
构造方法
public ConsumeQueue( final String topic, final int queueId, final String storePath, final int mappedFileSize, final DefaultMessageStore defaultMessageStore) { this.storePath = storePath; this.mappedFileSize = mappedFileSize; this.defaultMessageStore = defaultMessageStore; this.topic = topic; this.queueId = queueId; //存储路径${this.storePath}/{topic}/{queueId}/{fileName} String queueDir = this.storePath + File.separator + topic + File.separator + queueId; this.mappedFileQueue = new MappedFileQueue(queueDir, mappedFileSize, null); //分配一个存储单元大小(20B)的缓冲区 this.byteBufferIndex = ByteBuffer.allocate(CQ_STORE_UNIT_SIZE); //是否启用消息队列的扩展存储 if (defaultMessageStore.getMessageStoreConfig().isEnableConsumeQueueExt()) { this.consumeQueueExt = new ConsumeQueueExt( topic, queueId, StorePathConfigHelper.getStorePathConsumeQueueExt(defaultMessageStore.getMessageStoreConfig().getStorePathRootDir()), defaultMessageStore.getMessageStoreConfig().getMappedFileSizeConsumeQueueExt(), defaultMessageStore.getMessageStoreConfig().getBitMapLengthConsumeQueueExt() ); } }
加载(load)
-
Broker启动时,调用load加载ConsumeQueue。加载直接委托mappedFileQueue进行加载
public boolean load() { boolean result = this.mappedFileQueue.load(); log.info("load consume queue " + this.topic + "-" + this.queueId + " " + (result ? "OK" : "Failed")); //扩展存储存在则加载 if (isExtReadEnable()) { result &= this.consumeQueueExt.load(); } return result; }
恢复(recover)
-
Broker启动时会尝试恢复ConsumeQueue文件。
- 如果文件个数大于3个就从倒数第三个文件开始恢复,否则从第一个开始
- 循环遍历文件中的的所有数据,按照20个字节读取。知道全部读取完成
- 删除有效offset之后的文件
-
源码
public void