跳转至主要内容
版本: 5.0

消息存储与清理

本文档介绍了 Apache RocketMQ 如何存储消息,包括存储粒度、判定标准以及处理策略。

背景信息

基于 Apache RocketMQ 中 MessageQueue 的定义,消息按照 Broker 接收消息的顺序存储在队列中。理论上,一个队列可以存储的消息数量是无限的。

在实际部署场景中,消息无法永久存储,因为 Broker 的物理存储空间有限。因此,在部署消息时,您需要回答三个问题:使用什么标准来决定如何在 Broker 上存储消息?管理已存储消息的粒度是什么?当消息存储用量超过限制时必须采取什么措施?Apache RocketMQ 的消息存储和清理机制为上述问题提供了答案。

通过以下几个方面利用消息存储和清理机制,您可以更好地执行运维工作:

  • 存储 SLA:存储时长是指用户可以获取消息的时间段。该功能适用于需要较长消费周期、消息积压以及需要故障恢复的场景。

  • 存储成本的评估与控制:Apache RocketMQ 将消息存储在磁盘上。您可以评估存储空间并提前预留存储资源。

消息存储机制

工作原理

Apache RocketMQ 的每个节点都会将消息存储一段特定的时间。这段时间称为“存储时长”,用于确定消息的存储期限。在存储时长内的消息会被保留,而超过时长限制的消息无论是否被消费都会被清理。

以下部分描述了与消息存储机制相关的项目:

  • 管理粒度:Apache RocketMQ 基于节点(Broker)管理消息的存储时长。

  • 判定标准:以“消息存储时长”作为判定标准。相比于消息数量或大小,存储时长可以帮助您更高效地评估消息的价值。

  • 消息存储与消费状态无关:Apache RocketMQ 中的消息存储时长从消息生产的时间点开始计算,与消费状态无关。通过使用统一的计算策略,可以简化消息存储机制。

下图显示了消息在队列中的存储方式。消息存储

注意

管理粒度

Apache RocketMQ 基于 Broker 节点管理存储时长,原因如下:

  • 消息存储的优势:Apache RocketMQ 使用由物理日志队列和轻量级逻辑队列组成的统一两级组织方式来管理物理数据。这种方法提供了顺序读写、高吞吐量和高性能的优势。但是,使用此方法无法基于 Topic 或队列来管理消息存储。

  • 容量保证与数据安全:尽管 Apache RocketMQ 基于 Topic 或队列生成独立的存储文件,但这些文件共享相同的底层存储介质。您可以灵活地基于 Topic 或队列管理存储时长。如果集群的存储容量不足,可能无法满足存储 SLA。如果您希望以安全的方式管理消息,最好的方法是在不同的集群中使用不同的存储时长来存储消息。

消息存储与消费状态的关系

无论消息是否被消费,Apache RocketMQ 都统一管理消息的存储时长。

由于消费者不活跃或消费异常,消息可能会在队列中积压。目前针对此问题尚无有效的解决方案。如果所有未被消费的消息都被保留,存储空间将很快被耗尽。这会影响新消息的读写速度。

消费者可以根据存储时长来管理消息,从而确定每条消息的生命周期。消费者可以在存储时长内的任何时间消费消息,或者通过重置消费位点功能多次消费消息。

消息存储文件结构 Apache RocketMQ 消息默认存储在本地磁盘文件中,存储文件的根目录由配置参数 storePathRootDir 决定。存储结构如下图所示,其中 commitlog 文件夹存储物理消息文件,consumeCQueue 文件夹存储逻辑队列索引。MessageStore

消息清理机制

在 Apache RocketMQ 中,消息的指定存储时长与实际存储时长可能存在差异。这是因为消息存储在本地磁盘中。当本地磁盘空间不足时,系统会强制删除消息以确保服务的稳定性。因此,实际存储时长会短于指定的存储时长。

Apache RocketMQ 存储系统基于阿里云云原生技术开发。这使得所有实例都可以使用存储空间,而不受存储容量的限制。所有消息都根据其指定的存储时长进行存储。您无需担心因存储空间不足而导致消息被删除。

使用说明

根据业务需求增加存储时长

Apache RocketMQ 根据存储时长来控制是否保留消息。建议您根据业务需求指定较长的存储时长。更长的存储时长可以让您有更多的余地进行紧急故障恢复、紧急故障排查和消息回溯等操作。