在 RocketMQ 中如何处理大消息(如超过 4MB 的消息)?
在 RocketMQ 中,默认的最大消息大小通常是 4MB(不同版本可能略有差异,老版本可能是 128KB 或更小)。消息队列(MQ)的核心设计初衷是处理高并发、低延迟、小体积的数据流。如果将大文件或巨大的 Payload 直接塞入 MQ,会导致网络带宽被占满、Broker 内存暴涨、频繁触发 GC,甚至导致其他业务的消息堆积和延迟。
因此,处理大消息(超过 4MB)通常有以下几种方案。按照推荐程度从高到低排列如下:
方案一:使用外部存储(OSS/S3/HDFS)—— ⭐ 最优实践,业界标配
这是处理大消息最正规、最稳定的做法,被称为 "Claim Check"(认领凭证)模式。
工作流程:
- 上传数据:生产者(Producer)在发送消息前,先将大体积的数据(如图片、视频、超大 JSON)上传到对象存储(如 阿里云 OSS、腾讯云 COS、MinIO、HDFS 等)。
- 获取凭证:上传成功后,获取该文件的下载 URL 或唯一标识(Object Key)。
- 发送消息:生产者将这个 URL 作为普通小消息发送到 RocketMQ。
- 消费下载:消费者(Consumer)收到消息后,解析出 URL,从对象存储中下载真正的大数据进行处理。
- 清理数据(可选):处理完成后,消费者调用 API 删除对象存储中的文件,或者依赖对象存储的生命周期规则(TTL)自动清理。
优点:彻底解放 RocketMQ,保持其极高的吞吐量;不受消息大小限制。
缺点:引入了额外的存储组件,增加了系统的网络开销(多了一次上传和下载)。
方案二:消息压缩(Compression)—— 适合文本类大消息
如果你的大消息是 JSON、XML 或纯文本(比如 5MB - 10MB 的文本),它们通常具有极高的压缩比。
工作流程:
- RocketMQ 自带压缩:RocketMQ 默认会在 Producer 端对大于
4KB(compressMsgBodyOverHowmuch参数)的消息使用 ZIP 进行压缩。你可以确认该机制是否生效。 - 业务层手动压缩:在将数据转为 byte 数组发送给 MQ 之前,在业务代码中使用高压缩比的算法(如 Gzip, Snappy, LZ4, Zstd)进行压缩。消费者收到后先解压再反序列化。
优点:不需要引入外部存储,代码改造量小。
缺点:消耗 CPU 资源;如果数据本身已经是压缩格式(如 JPG 图片、PDF、视频),此方案无效。
方案三:修改 RocketMQ 参数放宽限制 —— 仅限“略微超标”的场景
如果你不想引入 OSS,且消息大小只是稍微超过 4MB(例如 6MB、8MB),可以通过修改 RocketMQ 的配置来提高限制。
⚠️ 注意:必须同时修改 Broker 端和 Producer 端的配置。
修改 Broker 端配置:
在 Broker 的配置文件(broker.conf)中增加或修改以下参数,然后重启 Broker:plaintext# 将最大消息大小修改为 10MB (10 * 1024 * 1024) maxMessageSize = 10485760修改 Producer 端配置:
在生产者的代码中,调整maxMessageSize属性:javaDefaultMQProducer producer = new DefaultMQProducer("your_group"); // 设置为 10MB producer.setMaxMessageSize(10 * 1024 * 1024); // 注意:如果发送的消息很大,发送超时时间也建议适当延长,默认是 3000ms producer.setSendMsgTimeout(5000);修改 Consumer 端配置(可选):
虽然消费端没有硬性的单条消息大小限制,但如果是拉取模式或批量消费,建议注意拉取批次大小避免 OOM。
优点:最简单,只需改配置。
缺点:会严重影响 RocketMQ 性能。大消息会导致 Broker 写入 PageCache 变慢,占用大量网络带宽,导致同一时刻的其他小消息排队,产生长尾延迟。
方案四:消息拆分(分块发送)—— 极不推荐,复杂度过高
将一个 10MB 的消息,在业务层面拆分成 5 个 2MB 的小消息。
工作流程:
- 生产者给这 5 个消息分配同一个
traceId,并标记chunkIndex(1/5, 2/5...)。 - 将它们发送到 RocketMQ。
- 消费者收到消息后,不能立刻处理,必须先把切片缓存起来(如存入 Redis)。
- 等所有切片都到达后,消费者再将其拼接成完整的 10MB 数据进行处理。
优点:无需修改 MQ 配置,无需外部存储。
缺点:极其复杂。需要处理乱序问题、部分切片丢失问题、并发组装时的内存泄漏问题,极其容易出 Bug。除非极端环境受限,否则千万不要用这种方案。
总结与建议
| 消息大小 | 数据类型 | 推荐处理方案 |
|---|---|---|
| < 4MB | 任意 | 直接使用 RocketMQ 发送。 |
| 4MB - 10MB | JSON / 文本 | 方案二:业务层 Gzip/LZ4 压缩后再发送。 |
| 4MB - 10MB | 无法压缩的二进制 | 方案三:评估 Broker 带宽后,适当调大 maxMessageSize 配置。 |
| > 10MB | 任意 | 方案一:坚决使用 OSS/S3 等对象存储 + RocketMQ 传递 URL。 |