RocketMQ 基础学习
一、RocketMQ
Apache RocketMQ 是阿里巴巴研发并捐赠给 Apache 基金会的开源分布式消息中间件,定位为云原生、金融级消息引擎,核心特性为高吞吐、低延迟、高可用、强一致性,是分布式系统异步通信的核心组件。
核心应用场景:
- 异步解耦:拆分核心链路(如订单下单 → 库存扣减 → 物流创建 → 消息通知)
- 流量削峰:承接秒杀、大促等突发流量(如秒杀请求先入队列,消费端匀速处理)
- 日志收集:分布式日志汇聚(如 ELK 架构中作为日志传输通道)
- 分布式事务:基于事务消息实现最终一致性(如支付结果同步至会员系统)
- 实时计算:对接 Flink/Spark 实现流处理(如实时订单统计)
- 系统解耦:微服务间无侵入通信(替代 RPC 直连)
核心通信模型:
- 发布/订阅(Pub/Sub):主流模式,基于 Topic 实现一对多通信
- 点对点(P2P):基于 Consumer Group 负载均衡实现一对一消费
二、核心组件
| 组件 | 核心说明 | 关键补充 |
|---|---|---|
| Producer(生产者) | 发送消息到 Broker,支持同步、异步、单向发送 | 1. 支持本地事务表 + 事务消息 2. 可配置重试次数(默认 3 次) 3. 批量发送需保证单批 < 4MB |
| Consumer(消费者) | 从 Broker 拉取/接收消息,支持集群/广播模式 | 1. 推模式基于长轮询(默认 30s 超时) 2. 拉模式需手动管理 Offset 3. 消费线程数可配置(默认 20) |
| Topic | 消息的逻辑分类,类似“消息频道” | 1. 一个 Topic 对应多个 MessageQueue(默认 4 个) 2. 建议按业务域划分(如 order_topic、pay_topic) 3. 支持动态扩容队列数 |
| Broker | 消息存储与转发核心节点 | 1. 存储结构:CommitLog(统一存储)+ ConsumeQueue(索引) 2. 主从架构:Master 写 + Slave 读 3. Dledger 模式实现自动主从切换 4. 默认保留消息 72 小时,可配置 |
| NameServer | 轻量级注册中心,管理 Broker 路由 | 1. 无状态,节点间不通信 2. 客户端每 30s 拉取一次路由信息 3. 集群部署需保证至少 2 个节点 |
| Namespace | 多租户/多环境隔离(阿里云商业版特性) | 1. 开源版可通过 Topic 前缀模拟(如 dev_order_topic) 2. 隔离范围:Topic、Group、配置 3. 避免不同环境 Topic 命名冲突 |
| MessageQueue | Topic 的物理分区 | 1. 队列数决定并发消费能力 2. 集群消费时,队列均匀分配给 Consumer 实例 3. 顺序消息需保证同业务键入同队列 |
| Offset | 消费进度标识 | 1. 集群消费:Offset 存储在 Broker 2. 广播消费:Offset 存储在本地 3. 支持重置 Offset(按时间/位置) |
架构核心特点:
- NameServer 无状态 → 易扩容
- Broker 主从/Dledger → 高可用
- Producer/Consumer 动态发现 Broker → 无单点
- 消息顺序写入 CommitLog → 高性能
三、生产者组(Producer Group)与消费者组(Consumer Group)
1. Producer Group(生产者组)
- 定义:逻辑上相同的 Producer 实例集合(如订单服务的多个生产者节点)
- 核心作用:
- 事务消息回查:Broker 回查未确认的事务消息时,会向该 Group 内任意在线实例发起回调
- 运维管控:日志追踪、权限管理、监控指标聚合
- 最佳实践:
- 事务消息必须指定唯一 Producer Group
- 不同业务系统使用不同 Group(如 order-producer、pay-producer)
- 非事务场景可复用,但不建议(便于问题定位)
2. Consumer Group(消费者组)
- 定义:协同消费同一 Topic 的 Consumer 实例集合
- 核心作用:
- 负载均衡:MessageQueue 自动分配给组内实例(队列数 ≥ 实例数最佳)
- 高可用:实例宕机后,其负责的队列由其他实例接管
- 独立进度:每个 Group 维护自己的 Offset,互不干扰
- 消费模式对比(增强版):
模式 核心逻辑 适用场景 注意事项 集群模式(CLUSTERING) 每条消息仅被组内一个实例消费 绝大多数业务(订单、支付、通知) 实例数 ≤ 队列数,否则部分实例空闲 广播模式(BROADCASTING) 每条消息被组内所有实例消费 配置推送、全量数据同步 无重试机制,需自行保证幂等
黄金原则:
- 一个业务逻辑 = 一个 Consumer Group
- 同一 Group 内的 Consumer 必须订阅相同的 Topic/Tag
- 不同业务订阅同一 Topic 必须用不同 Group
四、消费模式:推(Push) vs 拉(Pull)
RocketMQ 的“推模式”是伪推真拉(基于长轮询),框架封装了拉取逻辑;拉模式需手动控制全流程。
| 特性 | 推模式(DefaultMQPushConsumer) | 拉模式(LitePullConsumer) |
|---|---|---|
| 核心API | DefaultMQPushConsumer | LitePullConsumer(5.x 推荐) |
| 消息获取 | 框架自动长轮询拉取,回调监听器 | 应用主动调用 poll() 拉取 |
| Offset 管理 | 自动提交(默认 5s)/手动提交 | 强制手动提交(commitSync()) |
| 队列分配 | 自动 Rebalance(默认 20s 检测) | 手动 assign()/自动 subscribe() |
| 流控能力 | 内置参数控制(如 pullThresholdForQueue) | 完全由应用控制(可自定义限流) |
| 并发控制 | 配置消费线程数(consumeThreadMin) | 手动控制线程池 |
| 适用场景 | 通用业务、快速开发、大部分场景 | 批处理、精准限流、流计算集成 |
| 开发成本 | 低(框架封装) | 中高(需处理异常/重试) |
| 资源占用 | 适中 | 灵活(可按需拉取) |
推模式示例
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import java.nio.charset.StandardCharsets;
public class PushConsumerExample {
public static void main(String[] args) throws MQClientException {
// 1. 创建消费者实例,指定Group
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("order-consumer-group");
// 2. 配置NameServer地址
consumer.setNamesrvAddr("127.0.0.1:9876");
// 3. 配置消费起始位置(首次启动从最新位置开始)
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
// 4. 配置消费线程数
consumer.setConsumeThreadMin(10);
consumer.setConsumeThreadMax(20);
// 5. 订阅Topic,Tag过滤(* 表示所有Tag)
consumer.subscribe("order_topic", "create_order || pay_success");
// 6. 注册消息监听器(核心消费逻辑)
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
try {
for (MessageExt msg : msgs) {
// 处理消息(示例:打印消息内容)
String msgBody = new String(msg.getBody(), StandardCharsets.UTF_8);
System.out.printf("消费消息:Topic=%s, Tag=%s, Key=%s, Body=%s%n",
msg.getTopic(), msg.getTags(), msg.getKeys(), msgBody);
// 模拟业务处理
handleBusiness(msg);
}
// 消费成功
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} catch (Exception e) {
// 消费失败,触发重试(默认最多 16 次)
System.err.println("消费失败,触发重试:" + e.getMessage());
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
});
// 7. 启动消费者
consumer.start();
System.out.println("推模式消费者启动成功");
// 8. 优雅关闭(JVM 退出时)
Runtime.getRuntime().addShutdownHook(new Thread(consumer::shutdown));
}
// 业务处理逻辑
private static void handleBusiness(MessageExt msg) throws Exception {
// 幂等处理(根据 msg.getKeys() 做唯一键校验)
String uniqueKey = msg.getKeys();
if (checkDuplicate(uniqueKey)) {
System.out.println("消息已处理,跳过:" + uniqueKey);
return;
}
// 实际业务逻辑...
}
// 幂等校验(示例)
private static boolean checkDuplicate(String uniqueKey) {
// 可基于Redis/数据库实现
return false;
}
}
拉模式示例
import org.apache.rocketmq.client.consumer.LitePullConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class PullConsumerExample {
public static void main(String[] args) throws MQClientException {
// 1. 创建拉模式消费者
LitePullConsumer consumer = LitePullConsumer.createPullConsumer("batch-consumer-group");
// 2. 配置参数
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.setPullBatchSize(32); // 每次拉取32条
// 3. 订阅Topic
consumer.subscribe("order_topic", "*");
// 4. 启动消费者
consumer.start();
System.out.println("拉模式消费者启动成功");
// 5. 循环拉取消息
try {
while (!Thread.currentThread().isInterrupted()) {
// 拉取消息(超时时间 1000ms)
List<MessageExt> msgs = consumer.poll(1000);
if (!msgs.isEmpty()) {
// 批量处理消息
for (MessageExt msg : msgs) {
String body = new String(msg.getBody(), StandardCharsets.UTF_8);
System.out.printf("拉取消息:Key=%s, Body=%s%n", msg.getKeys(), body);
}
// 手动提交Offset(确保消息处理完成后提交)
consumer.commitSync();
System.out.println("批量消费完成,已提交Offset");
}
}
} finally {
// 优雅关闭
consumer.shutdown();
}
}
}
生产建议:
- 90% 场景优先使用推模式(开发效率高)
- 批处理/流计算场景使用拉模式
- 推模式建议开启手动提交 Offset(避免消息丢失)
五、消息类型详解
1. 普通消息(Normal Message)
最基础类型,无特殊语义,适用于大部分非核心场景。
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
public class NormalMessageProducer {
public static void main(String[] args) throws Exception {
// 1. 创建生产者实例
DefaultMQProducer producer = new DefaultMQProducer("normal-producer-group");
producer.setNamesrvAddr("127.0.0.1:9876");
// 设置重试次数
producer.setRetryTimesWhenSendFailed(3);
// 2. 启动生产者
producer.start();
// 3. 构建消息(Topic, Tag, Key, Body)
Message msg = new Message(
"normal_topic", // Topic
"common_tag", // Tag
"ORDER_10086", // Key(用于消息追踪/去重)
"普通消息内容".getBytes(StandardCharsets.UTF_8)
);
// 4. 同步发送消息
SendResult sendResult = producer.send(msg);
System.out.printf("发送成功:MsgId=%s, QueueId=%d%n",
sendResult.getMsgId(), sendResult.getMessageQueue().getQueueId());
// 5. 关闭生产者
producer.shutdown();
}
}
2. 顺序消息(Ordered Message)
保证同一业务键(如订单ID)的消息按生产顺序消费,核心是“同Key入同队列 + 单线程消费”。
// 生产者
public class OrderedProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("order-producer-group");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
// 模拟订单流程:创建→支付→发货(需保证顺序)
String[] orderSteps = {"create", "pay", "ship"};
String orderId = "ORDER_1001";
for (String step : orderSteps) {
Message msg = new Message(
"order_topic",
"order_step",
orderId,
String.format("订单%s:%s", orderId, step).getBytes()
);
// 按订单ID哈希选择队列(保证同订单入同队列)
SendResult result = producer.send(msg, (mqs, msg1, arg) -> {
String oid = (String) arg;
int index = Math.abs(oid.hashCode()) % mqs.size();
return mqs.get(index);
}, orderId);
System.out.printf("发送顺序消息:%s, QueueId=%d%n", step, result.getMessageQueue().getQueueId());
}
producer.shutdown();
}
}
// 消费者(必须用 MessageListenerOrderly)
public class OrderedConsumer {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("order-consumer-group");
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("order_topic", "order_step");
// 顺序消费监听器(单线程处理队列消息)
consumer.registerMessageListener((msgs, context) -> {
MessageExt msg = msgs.get(0);
String body = new String(msg.getBody(), StandardCharsets.UTF_8);
System.out.printf("顺序消费:QueueId=%d, Content=%s%n",
msg.getQueueId(), body);
// 手动提交Offset(顺序消费建议手动提交)
context.setAutoCommit(false);
return ConsumeOrderlyStatus.SUCCESS;
});
consumer.start();
System.out.println("顺序消费者启动成功");
}
}
顺序消息注意事项:
- 队列数决定并发度(队列越多,并发越高)
- 消费失败会阻塞整个队列,需快速失败或跳过
- 不建议用于高并发场景
3. 延迟消息(Delay Message)
延迟固定时间后投递,仅支持 18 个固定等级(开源版无自定义延迟)。
public class DelayMessageProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("delay-producer-group");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message(
"delay_topic",
"delay_tag",
"ORDER_10086",
"订单15分钟未支付,自动取消".getBytes()
);
// 设置延迟等级(3=10秒,详见附录)
msg.setDelayTimeLevel(5); // 等级5=1分钟
SendResult result = producer.send(msg);
System.out.println("延迟消息发送成功:" + result.getMsgId());
producer.shutdown();
}
}
4. 事务消息(Transactional Message)
实现“本地事务 + 消息发送”的最终一致性,核心流程:半消息 → 本地事务 → 提交/回滚。
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
public class TransactionProducer {
public static void main(String[] args) throws Exception {
// 1. 创建事务生产者
TransactionMQProducer producer = new TransactionMQProducer("tx-producer-group");
producer.setNamesrvAddr("127.0.0.1:9876");
// 2. 设置事务监听器
producer.setTransactionListener(new TransactionListener() {
// 执行本地事务
@Override
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
String orderId = msg.getKeys();
try {
// 执行本地事务(如扣减库存、创建订单)
boolean success = executeLocalDBTransaction(orderId);
return success ? LocalTransactionState.COMMIT_MESSAGE
: LocalTransactionState.ROLLBACK_MESSAGE;
} catch (Exception e) {
// 未知状态,等待回查
return LocalTransactionState.UNKNOW;
}
}
// 事务回查(Broker主动调用)
@Override
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
String orderId = msg.getKeys();
// 查询本地事务状态
boolean isSuccess = queryLocalTransactionStatus(orderId);
return isSuccess ? LocalTransactionState.COMMIT_MESSAGE
: LocalTransactionState.ROLLBACK_MESSAGE;
}
});
producer.start();
// 3. 发送事务消息
Message msg = new Message(
"tx_topic",
"tx_tag",
"ORDER_10086",
"订单支付事务消息".getBytes()
);
producer.sendMessageInTransaction(msg, null);
// 4. 优雅关闭
// producer.shutdown();
}
// 模拟本地事务执行
private boolean executeLocalDBTransaction(String orderId) {
// 实际业务逻辑...
return true;
}
// 模拟查询本地事务状态
private boolean queryLocalTransactionStatus(String orderId) {
// 实际查询数据库...
return true;
}
}
5. 批量消息(Batch Message)
一次发送多条消息,提升吞吐,需满足:同Topic、同Tag、无延迟/事务、单批 < 4MB。
public class BatchProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("batch-producer-group");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
// 构建批量消息
List<Message> msgList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
msgList.add(new Message(
"batch_topic",
"batch_tag",
"BATCH_" + i,
("批量消息" + i).getBytes()
));
}
// 拆分超大批量(避免超过4MB)
ListSplitter splitter = new ListSplitter(msgList);
while (splitter.hasNext()) {
List<Message> subList = splitter.next();
SendResult result = producer.send(subList);
System.out.println("批量发送成功:" + subList.size() + "条");
}
producer.shutdown();
}
// 批量消息拆分器(处理超大批量)
static class ListSplitter implements Iterator<List<Message>> {
private final int SIZE_LIMIT = 1024 * 1024 * 4; // 4MB
private final List<Message> messages;
private int currIndex;
public ListSplitter(List<Message> messages) {
this.messages = messages;
}
@Override
public boolean hasNext() {
return currIndex < messages.size();
}
@Override
public List<Message> next() {
int nextIndex = currIndex;
int totalSize = 0;
for (; nextIndex < messages.size(); nextIndex++) {
Message msg = messages.get(nextIndex);
int size = msg.getBody().length + 20; // 消息体+固定头
if (size > SIZE_LIMIT) {
throw new IllegalArgumentException("单条消息超过4MB限制");
}
if (totalSize + size > SIZE_LIMIT) {
break;
}
totalSize += size;
}
List<Message> subList = messages.subList(currIndex, nextIndex);
currIndex = nextIndex;
return subList;
}
}
}
6~9. 扩展消息类型
| 类型 | 实现方式 | 核心使用场景 | 注意事项 | ||
|---|---|---|---|---|---|
| 广播消息 | consumer.setMessageModel(MessageModel.BROADCASTING) | 配置推送、全量数据同步 | 无重试,需自行保证幂等 | ||
| 过滤消息 | 1. Tag过滤:`subscribe("topic", "tag1 | tag2")<br>2. SQL过滤:subscribe("topic", MessageSelector.bySql("score > 80"))` | 按业务属性筛选消息 | SQL过滤需在Broker开启 enablePropertyFilter=true | |
| 重试消息 | 消费失败自动重试,默认 16 次 | 临时异常重试(如网络抖动) | 重试间隔逐渐增加(1s→5s→30s...) | ||
| 死信消息 | 重试 16 次失败后进入 %DLQ%{group} | 永久处理失败的消息 | 需人工介入处理,避免消息丢失 |
六、RocketMQ 优缺点
优点
| 维度 | 核心优势 | 补充说明 |
|---|---|---|
| 高性能 | 单机 10w+ TPS,毫秒级延迟 | CommitLog 顺序写,ConsumeQueue 内存索引 |
| 高可靠 | 消息持久化 + 主从复制 + Dledger 自动容灾 | 支持同步/异步刷盘,满足金融级可靠性 |
| 功能丰富 | 原生支持顺序、事务、延迟、批量消息 | 相比 Kafka 功能更贴合业务场景 |
| 灵活消费 | 集群/广播、推/拉、Tag/SQL 过滤 | Offset 可灵活重置(按时间/位置) |
| 运维友好 | 支持消息轨迹、死信队列、监控指标 | 开源版 Dashboard 可可视化管理 |
| 生态完善 | 原生支持 Spring Boot/Spring Cloud | 对接 Flink/Spark 实现流计算 |
| 云原生 | 5.x 版本支持 Proxy 架构 + gRPC | 更适配 Kubernetes 容器化部署 |
缺点
| 问题 | 影响范围 | 解决方案 |
|---|---|---|
| 延迟不灵活 | 开源版仅支持 18 个固定等级 | 1. 商业版支持自定义延迟 2. 开源版可结合定时任务模拟 |
| 资源消耗高 | 内存/磁盘 IO 高于 Kafka | 1. 合理配置 Broker 内存 2. 定期清理过期消息 |
| 运维复杂度 | 需维护 NameServer + Broker 集群 | 1. 采用 Dledger 自动主从切换 2. 配置监控告警(堆积/失败率) |
| 使用限制多 | 批量/事务消息约束多 | 遵循最佳实践,封装通用发送工具类 |
| 学习曲线陡 | 新人上手慢 | 先掌握核心概念,再深入底层原理 |
| 管控台体验 | 开源版 Dashboard 功能简单 | 1. 商用版阿里云 MQ 控制台 2. 第三方开源管控台(如 RocketMQ-Console-NG) |
七、最佳实践
1. 命名规范(标准化)
| 组件 | 命名格式 | 示例 |
|---|---|---|
| Topic | {业务域}_{功能}_{环境} | order_create_prod, pay_notify_test |
| Producer Group | {业务}_{角色}_{环境}_producer | order_service_prod_producer |
| Consumer Group | {业务}_{角色}_{环境}_consumer | pay_notify_prod_consumer |
| Key | {业务标识}_{唯一ID} | ORDER_10086, USER_8888 |
2. 核心避坑指南
- 幂等性必做:消费端必须基于 Key 做幂等(如 Redis 分布式锁、数据库唯一键)
- 消息 Key 必设:用于消息追踪、去重、事务回查
- 避免超大消息:单条消息建议 < 1MB,超大消息用分片 + 文件存储
- 合理设置队列数:Topic 队列数建议为 Consumer 实例数的 2~3 倍(保证负载均衡)
- 消费线程数配置:根据业务 QPS 调整,默认 20 可满足大部分场景
- 重试次数控制:非核心业务可减少重试次数(如
setMaxReconsumeTimes(3)) - 死信队列监控:配置告警,避免死信消息堆积
- 事务消息回查幂等:
checkLocalTransaction可能多次调用,需保证幂等
3. 监控核心指标
| 指标 | 监控阈值 | 说明 |
|---|---|---|
| 消息堆积量 | > 10000 | brokerOffset - consumerOffset > 10000 |
| 消费失败率 | > 1% | 失败次数/总消费次数 > 1% |
| 发送成功率 | < 99.99% | 发送失败需及时告警 |
| Broker 磁盘使用率 | > 80% | 避免磁盘满导致消息写入失败 |
| NameServer 存活数 | < 2 | 保证至少 2 个 NameServer 节点可用 |
八、附录
1. 延迟等级对照表(默认)
| 等级 | 延迟时间 | 等级 | 延迟时间 | 等级 | 延迟时间 |
|---|---|---|---|---|---|
| 1 | 1秒 | 7 | 3分钟 | 13 | 9分钟 |
| 2 | 5秒 | 8 | 4分钟 | 14 | 10分钟 |
| 3 | 10秒 | 9 | 5分钟 | 15 | 20分钟 |
| 4 | 30秒 | 10 | 6分钟 | 16 | 30分钟 |
| 5 | 1分钟 | 11 | 7分钟 | 17 | 1小时 |
| 6 | 2分钟 | 12 | 8分钟 | 18 | 2小时 |
2. 核心配置参数(常用)
| 组件 | 参数名 | 默认值 | 建议值 | 说明 |
|---|---|---|---|---|
| Producer | retryTimesWhenSendFailed | 3 | 3~5 | 同步发送失败重试次数 |
| Producer | retryTimesWhenSendAsyncFailed | 2 | 2 | 异步发送失败重试次数 |
| Consumer | consumeThreadMin | 20 | 10~50 | 最小消费线程数 |
| Consumer | consumeThreadMax | 20 | 50~200 | 最大消费线程数 |
| Consumer | maxReconsumeTimes | 16 | 3~10 | 最大重试次数 |
| Consumer | consumeTimeout | 15分钟 | 3~5分钟 | 消费超时时间 |
| Broker | messageStoreExpireHours | 72 | 24~72 | 消息保留时长(小时) |
3. 常用运维命令
# 1. 查看 Topic 信息
mqadmin topicList -n 127.0.0.1:9876
mqadmin topicStatus -n 127.0.0.1:9876 -t order_topic
# 2. 查看消费堆积
mqadmin consumerProgress -n 127.0.0.1:9876 -g order-consumer-group
# 3. 重置消费 Offset(按时间)
mqadmin resetOffsetByTime -n 127.0.0.1:9876 -t order_topic -g order-consumer-group -s "2026-03-01 00:00:00"
# 4. 查看死信队列
mqadmin queryMsgByTopic -n 127.0.0.1:9876 -t %DLQ%order-consumer-group
九、总结
核心关键点
- 核心架构:NameServer(路由)+ Broker(存储)+ Producer/Consumer(收发),无状态设计保证高可用;
- 核心特性:支持顺序、事务、延迟、批量消息,满足绝大多数业务场景;
- 消费模式:推模式(90%场景)简单高效,拉模式适用于批处理/精准控制;
- 生产准则:必须保证消费幂等、合理设置重试次数、监控消息堆积;
- 避坑重点:顺序消息阻塞风险、事务消息回查幂等、批量消息大小限制。
适用场景总结
- 推荐使用:异步解耦、流量削峰、分布式事务、普通业务通知;
- 谨慎使用:超高并发(百万 TPS)、自定义延迟、极致低延迟(微秒级);
- 不建议使用:点对点即时通信、小数据量高频次消息(建议用 RPC)。