消息类型

RocketMQ 提供5种消息发送方式,根据业务对可靠性 和实时性的不同要求选择。

一、同步消息(Sync)

特征:发送后阻塞等待 Broker 返回结果,有回执才继续。

  • 适用场景:重要通知(短信、转账成功通知)
  • 优点:可靠性最高,发送方知道消息一定到达
  • 缺点:发送方阻塞,吞吐量较低
复制代码
SendResult result = producer.send(message);  // 同步阻塞等待

之前写的所有 producer.send() 默认就是同步消息。


二、异步消息(Async)

特征:发送后不阻塞,结果通过回调函数异步返回。

  • 适用场景:响应时间敏感但对结果即时性要求不高的场景(订单中间状态更新)
复制代码
producer.send(message, new SendCallback() {
    @Override
    public void onSuccess(SendResult sendResult) {
        System.out.println("发送成功: " + sendResult);
    }
    @Override
    public void onException(Throwable e) {
        System.out.println("发送失败: " + e.getMessage());
    }
});
// 这里不会阻塞,先执行下面的代码,等结果回来才回调上面

执行顺序 :先执行 send() 下面的代码 → 等 Broker 返回结果 → 再触发回调 onSuccess/onException。

所以日志是"先发完下面的,再打印上面的回调结果"。

报错 MQClientException 是因为异步回调还没执行完,producer 就被 shutdown 了。解决方案:主线程等待一段时间再关闭。


三、单向消息(Oneway)

特征:只管发,不需要任何回执,不关心结果。

  • 适用场景:日志收集、埋点数据等允许丢失的场景
  • 优点:吞吐量最高
  • 缺点:不保证到达
复制代码
producer.sendOneway(message);  // 发了就忘,无返回值

四、延时消息(Delay)

特征:消息发送后不会立即投递给消费者,而是等待指定时间后再投递。

  • 适用场景:订单超时取消(30分钟未支付)、定时提醒
复制代码
message.setDelayTimeLevel(3);  // 延时等级 3 = 10s
producer.send(message);

RocketMQ 不支持任意时间的延时,只支持预设的18个延时等级:

|-------|-----|-------|----|-------|-----|
| level | 延时 | level | 延时 | level | 延时 |
| 1 | 1s | 7 | 3m | 13 | 9m |
| 2 | 5s | 8 | 4m | 14 | 10m |
| 3 | 10s | 9 | 5m | 15 | 20m |
| 4 | 30s | 10 | 6m | 16 | 30m |
| 5 | 1m | 11 | 7m | 17 | 1h |
| 6 | 2m | 12 | 8m | 18 | 2h |

需要自定义延时时间?可以修改 Broker 配置 messageDelayLevel。


五、批量消息(Batch)

特征:将多条消息打包成一次请求发送,减少网络开销。

  • 适用场景:需要一次性发送大量小消息
  • 限制 :同一批次的消息必须 Topic 相同,且总大小 不超过 1MiB

    List msgList = new ArrayList<>();
    msgList.add(new Message("topic7", "tag1", "msg1".getBytes()));
    msgList.add(new Message("topic7", "tag1", "msg2".getBytes()));
    msgList.add(new Message("topic7", "tag1", "msg3".getBytes()));

    SendResult result = producer.send(msgList); // 批量发送

超过 1MiB 怎么办?自己实现分批:ListUtils.partition(msgList, size) 拆成多个小批次。


六、五种消息类型对比总结

|--------|---------|-------|-------|-----------|
| 类型 | 是否等待回执 | 可靠性 | 吞吐量 | 典型场景 |
| 同步 | 阻塞等待 | ★★★★★ | ★★ | 短信、转账通知 |
| 异步 | 回调获取 | ★★★★ | ★★★★ | 订单状态流转 |
| 单向 | 不关心 | ★ | ★★★★★ | 日志、埋点 |
| 延时 | 同步/异步均可 | ★★★★ | ★★★ | 超时取消、定时通知 |
| 批量 | 同步/异步均可 | ★★★★ | ★★★★★ | 大批量小消息 |


七、消息生产者核心流程

复制代码
Producer 启动
    │
    ├─ 连接 NameServer(获取路由信息)
    │
    ├─ 选择发送方式:
    │   ├─ send()        → 同步等待回执
    │   ├─ send(callback) → 异步回调
    │   └─ sendOneway()  → 不等待
    │
    ├─ 选择 MessageQueue(负载均衡)
    │
    └─ 发送到 Broker → 返回 SendResult
         ├─ sendStatus: SEND_OK / FLUSH_DISK_TIMEOUT / SLAVE_NOT_AVAILABLE
         ├─ msgId: 全局唯一消息ID
         └─ queueOffset: 在队列中的偏移量
相关推荐
SL_staff17 小时前
从配置失效到逻辑复用:JVS-Logic 如何构建可治理的业务编排中枢
java·spring·产品
特立独行的猫A17 小时前
一份 Markdown 发十个平台:cspub 一稿多投
java·后端·python
文丑颜不良啊17 小时前
LeetCode1961~1980题目解析
java·leetcode
文丑颜不良啊18 小时前
LeetCode2001~2020题目解析
java·leetcode
用户37215742613518 小时前
Java 批量提取 Word 文档中的图片并保存到本地
java
SL_staff18 小时前
BI项目失败率90%?JVS如何用三阶闭环构建可落地的数据生产力平台
java·开源·全栈
nice_lcj52020 小时前
ThreadLocal 入门:它是怎么隔离数据的、为什么会导致内存泄漏
java·开发语言·后端·面试·并发编程·内存泄漏·threadlocal
秋天的怀念_David20 小时前
算法一千零一夜 · 第二十六夜 协议的母语
java·spring boot·算法
灿飞20 小时前
Kotlin与Java虚拟机八:控制流与 when:卫语句、上下文相关解析与穷尽性
java·kotlin
文丑颜不良啊21 小时前
LeetCode2021~2040题目解析
java·leetcode