文章目录
一、RocketMQ 概述
1.1 基本定义
RocketMQ 是阿里巴巴开源的一款分布式消息中间件(Message Queue),后捐赠给 Apache 软件基金会并于2017年成为顶级项目。它采用 Java 语言开发,具有高性能、高可靠、高实时、分布式等特点,能够处理海量消息堆积,支持毫秒级的消息投递。
1.2 核心特性
特性 | 说明 |
---|---|
高吞吐 | 单机支持10万级TPS |
高可用 | 主从架构+多副本机制 |
低延迟 | 消息投递延迟在毫秒级 |
可扩展 | 支持水平扩展 |
消息顺序 | 保证分区有序 |
事务消息 | 支持分布式事务 |
消息回溯 | 可按时间/偏移量重新消费 |
消息过滤 | 支持SQL92语法过滤 |
二、核心架构解析
2.1 基础架构图
2.2 核心组件
-
NameServer:
- 轻量级服务发现中心
- 无状态节点,可集群部署
- 负责Broker管理和路由信息维护
-
Broker:
- 消息存储和转发核心组件
- 主从架构(Master/Slave)
- 支持同步/异步刷盘策略
-
Producer:
- 消息生产者
- 支持同步/异步/单向发送
- 自动负载均衡
-
Consumer:
- 消息消费者
- 支持Push/Pull两种模式
- 支持集群消费和广播消费
三、主要应用场景
3.1 异步解耦
典型场景:用户注册后需要发送邮件和短信通知
// 传统同步方式
public void register(User user) {
// 1. 注册用户
userDao.save(user);
// 2. 发送邮件(同步阻塞)
emailService.sendWelcomeEmail(user);
// 3. 发送短信(同步阻塞)
smsService.sendVerificationSMS(user);
}
// 使用RocketMQ异步解耦
public void register(User user) {
// 1. 注册用户
userDao.save(user);
// 2. 发送注册成功事件
Message message = new Message("USER_REGISTER",
JSON.toJSONString(user).getBytes());
rocketMQTemplate.send(message);
}
优势:
- 注册流程响应时间从500ms降低到100ms
- 邮件/SMS服务故障不影响主流程
- 方便扩展新的后续操作(如增加积分)
3.2 流量削峰
典型场景:电商秒杀系统
// 秒杀请求处理
@PostMapping("/seckill")
public Result seckill(Long itemId) {
// 1. 验证用户资格
if(!checkUser(userId)) {
return Result.error("非法请求");
}
// 2. 将请求放入消息队列
Message message = new Message("SECKILL_ORDER",
JSON.toJSONString(new OrderRequest(itemId, userId)).getBytes());
SendResult result = producer.send(message);
// 3. 返回排队结果
return Result.success("请求已进入处理队列");
}
// 消费者处理
public class OrderConsumer {
@RocketMQMessageListener(topic = "SECKILL_ORDER", consumerGroup = "order_group")
public void handleOrder(OrderRequest request) {
// 数据库操作(控制并发量)
orderService.processOrder(request);
}
}
优势:
- 将10000 QPS的瞬时流量平滑为1000 QPS处理
- 避免数据库被突发流量击垮
- 未处理的请求可在队列中等待
3.3 数据同步
典型场景:数据库与Elasticsearch同步
// 数据库变更监听(通过CDC或binlog)
public void onDataChange(DataChangeEvent event) {
Message message = new Message("DATA_SYNC_TOPIC",
JSON.toJSONString(event).getBytes());
rocketMQTemplate.send(message);
}
// ES消费者
public class ESConsumer {
@RocketMQMessageListener(topic = "DATA_SYNC_TOPIC", consumerGroup = "es_group")
public void syncToES(DataChangeEvent event) {
if(event.getTable().equals("products")) {
Product product = productMapper.selectById(event.getId());
esClient.index(product);
}
}
}
优势:
- 实现准实时数据同步(秒级延迟)
- 避免直接耦合数据库和ES
- 支持多消费者(如同时同步到Redis)
3.4 分布式事务
典型场景:订单支付后扣减库存
// 订单服务
public void payOrder(Long orderId) {
// 1. 开启事务消息
TransactionMQProducer producer = new TransactionMQProducer();
Message message = new Message("ORDER_PAID",
JSON.toJSONString(orderId).getBytes());
// 2. 发送事务消息
TransactionSendResult result = producer.sendMessageInTransaction(message, null);
}
// 事务监听器
public class OrderTransactionListener implements TransactionListener {
@Override
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
try {
// 执行本地事务(更新订单状态)
orderService.updateStatus(orderId, PAID);
return LocalTransactionState.COMMIT_MESSAGE;
} catch(Exception e) {
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
@Override
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
// 检查本地事务状态
Order order = orderService.getById(orderId);
return order.getStatus() == PAID ?
LocalTransactionState.COMMIT_MESSAGE :
LocalTransactionState.ROLLBACK_MESSAGE;
}
}
// 库存服务消费者
public class StockConsumer {
@RocketMQMessageListener(topic = "ORDER_PAID", consumerGroup = "stock_group")
public void reduceStock(Long orderId) {
stockService.reduce(orderId);
}
}
优势:
- 保证订单状态和库存扣减的最终一致性
- 避免复杂的分布式事务管理
- 业务逻辑清晰分离
3.5 日志收集
典型场景:分布式系统日志集中处理
// 日志生产者
public class LogAspect {
@Around("execution(* com..service.*.*(..))")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
long cost = System.currentTimeMillis() - start;
// 发送日志消息
LogEntry log = new LogEntry(
pjp.getSignature().getName(),
cost,
System.currentTimeMillis());
Message message = new Message("SYS_LOG",
JSON.toJSONString(log).getBytes());
rocketMQTemplate.send(message);
return result;
}
}
// 日志消费者
public class LogConsumer {
@RocketMQMessageListener(topic = "SYS_LOG", consumerGroup = "log_group")
public void handleLog(LogEntry log) {
// 1. 存储到ES
esClient.index(log);
// 2. 异常耗时告警
if(log.costTime > 1000) {
alertService.notifySlowCall(log.methodName, log.costTime);
}
}
}
优势:
- 不影响业务主流程性能
- 支持多目的地日志处理(存储/分析/监控)
- 可处理海量日志数据
四、典型行业应用案例
4.1 电商系统
- 订单状态流转:创建→支付→发货→完成
- 购物车与商品服务解耦
- 实时推荐系统:用户行为采集分析
4.2 金融支付
- 交易流水异步处理
- 对账系统数据同步
- 风控系统实时预警
4.3 物联网(IoT)
- 设备状态上报
- 指令下发队列
- 海量设备连接管理
4.4 游戏行业
- 玩家行为分析
- 游戏内通知广播
- 多服务器状态同步
五、与同类产品对比
特性 | RocketMQ | Kafka | RabbitMQ |
---|---|---|---|
开发语言 | Java | Scala/Java | Erlang |
吞吐量 | 10万级TPS | 百万级TPS | 万级TPS |
延迟 | 毫秒级 | 毫秒级 | 微秒级 |
消息顺序 | 分区有序 | 分区有序 | 队列有序 |
事务消息 | 支持 | 不支持 | 不支持 |
消息回溯 | 支持 | 支持 | 不支持 |
协议支持 | 自定义 | 自定义 | AMQP |
适用场景 | 金融/电商等 | 日志/大数据 | 企业应用 |
六、最佳实践建议
-
命名规范:
// 好的命名示例 Topic: "ORDER_PAYMENT_STATUS" ConsumerGroup: "inventory-service-group" Tag: "PAYMENT_SUCCESS"
-
消息大小控制:
- 建议单条消息不超过1MB
- 大消息考虑分片或存储引用
-
消费者实现:
@RocketMQMessageListener( topic = "YOUR_TOPIC", consumerGroup = "YOUR_CONSUMER_GROUP", consumeThreadNumber = 20, // 根据业务调整 consumeTimeout = 30L // 超时时间 ) public class YourConsumer implements RocketMQListener<String> { @Override public void onMessage(String message) { // 处理消息(建议try-catch) try { processMessage(message); } catch(Exception e) { log.error("处理消息失败", e); throw e; // 触发重试 } } }
-
生产环境配置建议:
# Broker配置 brokerClusterName=DefaultCluster brokerName=broker-a brokerId=0 # 0表示Master,>0表示Slave flushDiskType=ASYNC_FLUSH # 异步刷盘提高性能 # 生产者配置 rocketmq.producer.group=your_producer_group rocketmq.producer.send-message-timeout=3000 rocketmq.producer.retry-times-when-send-failed=2
-
监控告警:
- 搭建RocketMQ控制台
- 监控关键指标:
- 消息堆积量
- 发送/消费TPS
- 消费延迟
- 设置合理阈值告警
七、常见问题解决方案
7.1 消息堆积处理
-
临时方案:
- 增加消费者实例
- 提高消费者并行度(调整consumeThreadNumber)
-
长期方案:
- 优化消费逻辑
- 升级硬件配置
- 考虑使用SQL过滤减少不必要消息
7.2 消息重复消费
-
解决方案:
public void processOrder(OrderMessage message) { // 幂等处理 if(orderService.isProcessed(message.getOrderId())) { return; // 已经处理过 } // 业务处理 orderService.process(message); }
-
实现方式:
- 数据库唯一约束
- Redis原子操作
- 分布式锁
7.3 顺序消息保证
// 生产者确保相同订单号发到同一队列
Message message = new Message();
message.setTopic("ORDER_STATUS_CHANGE");
message.setBody(JSON.toJSONBytes(order));
message.setKeys(order.getOrderId()); // 关键标识
// 使用MessageQueueSelector保证相同订单选择相同队列
producer.send(message, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
String orderId = msg.getKeys();
int index = Math.abs(orderId.hashCode()) % mqs.size();
return mqs.get(index);
}
}, null);
八、未来发展趋势
-
云原生支持:
- Kubernetes Operator
- Serverless架构适配
-
多协议支持:
- 兼容Kafka协议
- 支持MQTT等IoT协议
-
智能化运维:
- 自动扩缩容
- 智能消息路由
- 故障自愈
-
边缘计算:
- 轻量级部署
- 边缘-云端协同
RocketMQ作为成熟的分布式消息中间件,在数字化转型浪潮中将继续发挥关键作用,特别是在大规模分布式系统、微服务架构和云原生应用中,其价值将更加凸显。