RocketMQNotes

第 15 章:ConsumeQueue 与 Index

zjc 于 2026-01-15 发布

这是《RocketMQ 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 ConsumeQueue 把 CommitLog 中的物理消息组织成 Topic 和 Queue 的逻辑视图,IndexFile 提供按 Key 和时间查询的索引。两者都是派生数据,但它们直接决定消费效率和问题排查效率。

15.1 ConsumeQueue 结构

每个 Topic 的每个队列对应一个 ConsumeQueue 目录:

store/consumequeue/OrderTopic/
  0/
  1/
  2/
  3/

每个条目通常包含:

CommitLog offset
message size
tag hashcode

消费者流程:

read ConsumeQueue entry
  -> get CommitLog offset and size
  -> read message from CommitLog

15.2 逻辑位点

消费者位点指的是队列中的逻辑偏移:

Queue offset: 0, 1, 2, 3 ...

Broker 最大位点来自 ConsumeQueue 条目数:

Broker Offset = ConsumeQueue entries
Delayed = Broker Offset - Consumer Offset

同一个逻辑位点在不同 Broker 或重建后的集群中不一定指向相同物理消息,因此迁移和重放要格外谨慎。

15.3 Tag 过滤

ConsumeQueue 条目中保存 Tag hashcode,Broker 可以先做粗过滤:

consumer subscribes TagA
  -> compare entry tag hashcode
  -> candidate message sent to consumer
  -> client validates real tag

特点:

  1. 减少不必要消息传输;
  2. hash 冲突由客户端最终校验;
  3. 订阅关系必须一致;
  4. Tag 修改会影响过滤效果;
  5. 复杂表达式会消耗 Broker CPU。

15.4 IndexFile

IndexFile 支持按消息 Key 和时间范围查询:

query key = O202608250001
  -> hash to slot
  -> scan index entry list
  -> filter by key and time
  -> read CommitLog

常见字段:

  1. key hash;
  2. CommitLog offset;
  3. message size;
  4. timestamp;
  5. index chain。

IndexFile 便于排查,不是业务数据库查询引擎。高频业务查询应使用数据库或搜索引擎,而不是依赖消息索引。

15.5 索引构建

Broker 在消息写入 CommitLog 后异步分发:

CommitLog append
  -> ReputMessageService
  -> build ConsumeQueue
  -> build IndexFile

如果分发落后,可能出现:

  1. 消息已写入但消费者暂时看不到;
  2. 按消息 ID 查询和按 Key 查询结果不一致;
  3. Broker 流量高时索引构建延迟。

监控 dispatch lag 和队列最大位点,避免误判消息丢失。

15.6 重建与恢复

ConsumeQueue 和 IndexFile 理论上可以从 CommitLog 重建:

scan CommitLog
  -> parse message
  -> rebuild queue index
  -> rebuild key index

注意:

  1. 重建需要磁盘、CPU 和时间;
  2. 必须先备份原始 CommitLog;
  3. 重建期间影响服务;
  4. 需要验证队列位点;
  5. 严格按当前版本运维手册操作;
  6. 有副本时优先从副本恢复。

15.7 容量规划

估算:

ConsumeQueue size ≈ queue message count × entry size
Index size ≈ key count × index entry size × expansion factor
CommitLog size ≈ message body + overhead

规划时还要考虑:

  1. Topic 数量;
  2. 队列数量;
  3. 消息大小;
  4. Key 数量;
  5. 保留时间;
  6. 重试和死信;
  7. 轨迹 Topic;
  8. 运维余量。

15.8 常见问题

问题 排查
消费者看不到新消息 ConsumeQueue 构建延迟、位点、权限
按 Key 查不到 未设置 Key、索引延迟、索引过期
延迟突然增大 消费慢、Index 冷读、磁盘瓶颈
磁盘被索引占满 Topic、队列或 Key 过多
队列位点不一致 异常关机、手工重置、迁移
重建后查询异常 索引不完整或时间范围错误

本章小结

ConsumeQueue 是 Topic 队列的逻辑索引,Index 是面向排查的 Key 和时间索引。它们让 RocketMQ 兼顾顺序写吞吐和多维度读取,但也带来构建延迟、容量和恢复复杂度。生产治理要同时关注 CommitLog、ConsumeQueue、Index 和消费位点的一致性。

思考题

  1. 消费位点为什么是队列逻辑位点而不是 CommitLog 偏移量?
  2. Tag 粗过滤为什么仍需要客户端校验?
  3. Index 为什么不适合作为业务查询引擎?
  4. dispatch lag 会造成什么误判?
  5. 重建索引前为什么必须备份 CommitLog?