消息队列 (Message Queue)
本节介绍 Apache RocketMQ 中消息队列的定义、模型关系和内部属性。此外,本主题还提供了关于消息队列的版本兼容性信息和使用说明。
定义
队列是 Apache RocketMQ 中用于存储和传输消息的容器。队列是 Apache RocketMQ 消息存储的最小单位。
Apache RocketMQ 中的一个主题由多个队列组成。通过这种方式,队列支持水平分区和流式存储。
队列具有以下优势:
有序存储:队列天生具有顺序性,消息按入队顺序存储。最早的消息位于队列起始位置,最新的消息位于队尾。通过偏移量(Offset)来标记队列中消息的位置和顺序。
流式操作语义:Apache RocketMQ 的基于队列的存储允许消费者从特定偏移量读取一条或多条消息。这有助于实现聚合读取和回溯读取等功能。这些功能在 RabbitMQ 或 ActiveMQ 中是不具备的。
模型关系
下图展示了队列在 Apache RocketMQ 领域模型中的位置。
默认情况下,Apache RocketMQ 提供可靠的消息存储。所有成功发送的消息都会持久化存储在队列中。消息由生产者发送,由消费者客户端接收。每条消息均可保证至少被成功投递一次。
Apache RocketMQ 的队列模型类似于 Kafka 的分区模型。在 Apache RocketMQ 中,队列是主题的一部分。尽管消息由主题管理,但操作是在队列级别进行的。例如,当生产者向特定主题发送消息时,消息会被发送到该主题下的一个队列中。
您可以通过调整 Apache RocketMQ 中的队列数量来进行扩容或缩容。
内部属性
读写权限
定义:决定当前队列是否可以进行读写操作。
取值:由 Broker 定义。枚举值说明如下:
6:读写。当前队列既可以写入消息也可以读取消息。
4:只读。当前队列可以读取消息,但不能写入消息。
2:只写。当前队列可以写入消息,但不能读取消息。
0:读写不可用。当前队列不允许任何读写操作。
- 约束:读写权限与运维操作相关。建议不要频繁修改权限。
行为约束
每个主题包含一个或多个用于存储消息的队列。每个主题的队列数量与消息类型及实例所在的地域有关。队列数量不可随意更改。
版本兼容性
队列名称因 Apache RocketMQ Broker 的版本而异。差异如下:
Broker 3.x 和 4.x 版本:队列名称由主题名称、Broker ID 和队列 ID 组成,并绑定到物理节点。
Broker 5.x 版本:队列名称是一个由集群分配的全局唯一字符串,与物理节点解耦。
建议不要手动构建队列名称或将其绑定到其他操作中,否则在 Broker 更新时,这些队列名称可能无法解析。
使用说明
队列数量设置
您可以在创建或修改主题时指定 Apache RocketMQ 中的队列数量。建议配置较少的队列,避免添加不必要的队列。
主题中包含过多队列会导致以下问题:
- 集群元数据量增加:Apache RocketMQ 基于队列采集指标和监控数据。过多的队列可能导致元数据量剧增。
- 客户端负载过高:Apache RocketMQ 的消息读写基于队列执行。大量的队列可能会产生空轮询请求,从而增加系统负载。
扩容队列的场景
物理节点负载均衡
Apache RocketMQ 中每个主题的队列可以分布在不同的服务节点上。为确保集群扩容后的流量负载均衡,建议增加队列或将之前的队列迁移到新的服务节点上。
与 FIFO(顺序)消息相关的性能瓶颈
在 Apache RocketMQ Broker 4.x 版本中,FIFO 消息仅在队列级别生效。因此,FIFO 消息的并发性取决于队列数量。当系统出现性能瓶颈时,建议增加队列数量。