一,为什么选择RocketMq
特性 | RabbitMQ | ActiveMQ | RocketMQ | Kafka |
---|---|---|---|---|
协议支持 | AMQP、STOMP、MQTT、HTTP | AMQP、STOMP、OpenWire、MQTT | 自定义协议(Remoting) | 自定义协议(基于 TCP) |
消息模型 | 队列(点对点)、发布/订阅(通过 Exchange 绑定) | 队列(点对点)、发布/订阅(Topic) | 队列(点对点)、发布/订阅(Topic) | 发布/订阅(Topic + Partition) |
吞吐量 | 中等(万级 QPS) | 低(万级以下) | 高(十万级 QPS) | 极高(百万级 QPS) |
延迟 | 低(微秒级) | 中等(毫秒级) | 低(毫秒级) | 较高(毫秒级,依赖批量消费) |
消息持久化 | 支持(内存、磁盘) | 支持(KahaDB、JDBC) | 支持(CommitLog 磁盘持久化) | 支持(磁盘持久化,默认 7 天) |
事务支持 | 支持(轻量级事务,性能较低) | 支持(XA 分布式事务) | 支持(分布式事务消息) | 支持(0.11+ 版本提供事务) |
消息顺序性 | 单队列有序 | 单队列有序 | 单队列严格有序(分区内有序) | 单分区有序(全局无序) |
消息确认机制 | ACK(自动/手动) | ACK(自动/手动) | ACK(同步/异步) | Offset 提交(自动/手动) |
集群模式 | 主从模式(镜像队列)或 Federation 跨集群同步 | 主从模式(共享存储)或 Network of Brokers | 主从模式(多副本同步) + NameServer 路由 | 分区多副本(Leader-Follower)+ ZooKeeper 协调 |
扩展性 | 中等(依赖集群配置) | 低(集群性能受限) | 高(水平扩展 Topic 分区) | 极高(分区可动态扩展) |
社区生态 | 活跃(Erlang 社区主导) | 活跃度下降(Apache 项目) | 活跃(阿里开源,Apache 顶级项目) | 极活跃(LinkedIn 开源,Apache 顶级项目) |
典型应用场景 | 企业级消息中间件、实时通信、任务分发 | 传统企业应用(JMS 规范)、小型系统 | 电商交易、金融支付(高可靠、顺序消息) | 日志收集、流处理、大数据管道 |
优势 | 灵活的路由规则、多协议支持 | 支持 JMS 规范、轻量级部署 | 高吞吐、低延迟、强顺序性 | 超高吞吐、持久化能力强、生态完善 |
劣势 | 集群扩展复杂、吞吐量一般 | 性能低、社区维护不足 | 配置复杂、生态相对较小 | 延迟较高、运维复杂 |
备注 | 适合复杂路由场景(如死信队列、优先级队列) | ActiveMQ Artemis 是新一代版本(性能提升) | 支持消息轨迹、延迟消息、事务消息 | 与 Flink、Spark 等流处理框架深度集成 |
为什么选择rocketmq作为讲解的呢,因为有高吞吐,可以应对大部分应对电商秒杀、支付订单等高并发场景。跨服务的最终一致性(如订单与库存)。Java生态友好,文档丰富,运维成本低。
二,他有什么优缺点
优点
1, 高吞吐与低延迟,单机支持 10万级 TPS 的吞吐量,适用于电商、金融等高并发场景。
2. 高可用性与可靠性,基于 主从架构(Master-Slave) 和 多副本同步机制,支持自动故障切换(
3,事务消息支持,提供完整的事务消息机制(两阶段提交),确保本地事务与消息发送的原子性。
4,源码是java的,可以进行二次开发。
5,消息堆积量比较大,不会因为消息堆积量过大导致服务失效。
缺点
1,客户端支持语言不多。
2,JMS接口没实现。
3,监控工具有限,需要第三方工具。
4,兼容性一般。
三,消息队列的模型?
队列模型
一个生产者可以向某个队列发送消息,一个队列可以存多个生产者消息,一个队列有多个消费者消费。
发布/订阅模型
发布/订阅模型则采用主题(Topic)作为消息的中介,生产者向主题发布消息,多个消费者通过订阅主题来接收消息副本。此模式支持消息广播,例如新闻推送场景中,一条新闻会被所有订阅用户接收。
四,RocketMq的架构
RocketMq使用的模型是发布/订阅模型,他的架构如下:
1. Message(消息)
定义:消息是 RocketMQ 中最基本的数据单元,包含业务数据(消息体)和元数据(如 Topic、Tag、Key 等属性)。
作用:生产者将业务数据封装为消息发送到 Broker,消费者从 Broker 拉取消息进行消费。
关键属性:
Topic:消息所属的主题,用于分类和路由。
Tag:消息的二级标签,用于细粒度过滤(如区分订单的创建、支付等操作)。
Key:消息的唯一标识(用户自定义),通常用于查询或去重。
2. Topic(主题)
定义:Topic 是消息的逻辑分类,生产者发送消息到指定 Topic,消费者订阅 Topic 以接收消息。
作用:实现 发布/订阅模型 的基础,支持消息的广播或负载均衡消费。
特点:
消息隔离:不同 Topic 的消息相互独立(如 订单Topic 和 库存Topic)。
多消费者模式:一个 Topic 可被多个 Consumer Group 订阅,每个 Group 独立消费全量消息。
分区机制:Topic 可划分为多个队列(MessageQueue),提升并发处理能力。
3. Tag(标签)
定义:Tag 是 Topic 下的二级分类,用于对同一 Topic 中的消息进行更细粒度的过滤。
作用:消费者可以基于 Tag 选择性消费消息,避免全量接收 Topic 数据。
使用场景:
订单 Topic 中,通过 Tag 区分 创建订单、支付订单、取消订单 等操作。
日志 Topic 中,通过 Tag 区分 INFO、ERROR、DEBUG 等级别。
语法:消息发送时指定 Tag,消费者订阅时通过 TagA || TagB 格式过滤(支持 SQL92 表达式)。
4. Group(组)
RocketMQ 中有两种 Group 类型:生产者组 和 消费者组。
(1) Producer Group
一组生产相同 Topic 消息的生产者集合。
(2) Consumer Group
一组消费相同 Topic 消息的消费者集合。
消费模式:
集群模式:每条消息仅被 Group 内的一个消费者消费(默认)。
广播模式:每条消息被 Group 内的所有消费者消费。
五,如何保证消息不丢失呢?
生产:
在生产阶段,主要通过请求确认机制,来保证消息的可靠传递。
同步发送 + 重试机制:
使用 send() 同步发送消息,并捕获发送结果(SendResult)。若发送失败,开启重试机制(默认重试 2 次)。同步发送的时候,要注意处理响应结果和异常。如果返回响应 OK,表示消息成功发送到了 Broker,如果响应失败,或者发生其它异常,都应该重试。
存储:
Broker 收到消息后,若未持久化就宕机,导致消息丢失。
1、消息只要持久化到 CommitLog(日志文件)中,即使 Broker 宕机,未消费的消息也能重新恢复再消费。
2、Broker 的刷盘机制:同步刷盘和异步刷盘,不管哪种刷盘都可以保证消息一定存储在 pagecache 中(内存中),但是同步刷盘更可靠,它是 Producer 发送消息后等数据持久化到磁盘之后再返回响应给 Producer。
同步刷盘概念:当数据写入内存后,必须等待数据成功写入磁盘,才会返回成功响应。
异步刷盘概念:当数据写入内存后,立即返回成功响应,磁盘写入操作由后台线程异步完成。
如图:
消费:
等业务代码完成之后,再发送消费确认,因为偏移量没有确认的话,你再去拉取,还是那个消息。
六,如何保证消息的顺序执行?
顺序消息主要分成两种:
全局顺序消息(严格顺序)
所有消息按照严格先后顺序被生产和消费(性能较低)
实现方式:所有消息发送到同一个队列(MessageQueue)
适用场景:金融交易、库存扣减等强一致性场景
分区顺序消息(局部顺序)
同一业务ID的消息保证顺序,不同业务间无需顺序
实现方式:相同业务ID的消息发送到同一队列
适用场景:订单状态流转、物流状态更新等场景
局部顺序具体执行:
Producer端保证顺序
使用MessageQueueSelector接口自定义路由逻辑,根据业务ID(如订单ID)哈希到固定队列。
SendResult sendResult = producer.send(msg,
(mqs, msg, arg) -> {
int index = arg.hashCode() % mqs.size();
return mqs.get(index);
},
"业务ID");
Broker端存储顺序
每个队列在Broker中对应一个物理文件,消息严格按接收顺序追加到文件末尾(CommitLog顺序写)
Consumer端顺序消费
每个队列在同一时刻只能被一个消费者线程处理,消费者使用MessageListenerOrderly监听器
七,延时消息说一下,优缺点是?
概念:
延迟消息是消息队列(如 RocketMQ)提供的一种特殊消息类型,允许消息在发送后延迟一段时间(如 30 分钟)再被消费者消费。其核心目的是将定时任务逻辑从业务代码中剥离,由消息队列系统自动触发延迟投递,简化开发流程。
其实本质上:消息队列的“定时器”功能,替代传统方案(如数据库轮询、线程睡眠 Thread.sleep
等)
不支持任意级别,支持18个指定级别
延迟级别 | 1 | 2 | 3 | 4 | 5 | ... | 18 |
---|---|---|---|---|---|---|---|
时间 | 1s | 5s | 10s | 30s | 1m | ... | 2h |
机制:
存储:延迟消息存入特殊 Topic(SCHEDULE_TOPIC_XXX),每个延迟级别对应一个队列。
定时扫描:Broker 启动后台线程,按延迟级别轮询队列,到期后将消息转移到目标 Topic 供消费。
投递精度:因依赖轮询机制,可能存在微小误差(通常毫秒级)。
实例代码
Message msg = new Message("OrderTopic", "订单超时关闭".getBytes());
// 设置延迟级别为 4(对应 30 秒)
msg.setDelayTimeLevel(4);
producer.send(msg);
优点:
解耦业务与定时逻辑
延时消息将业务逻辑与定时任务解耦,无需业务层自行实现定时调度(如数据库轮询或线程休眠),简化代码复杂度。
高可靠性
RocketMQ 的延时消息和普通消息一样,支持持久化存储、重试机制和事务特性,保证消息不丢失。
预定义延迟级别
RocketMQ 提供 18 个固定的延迟级别,覆盖常见业务场景,开箱即用。
可扩展性
虽然不支持任意时间精度,但可通过修改 Broker 配置自定义延迟级别(如增加 15m、30m 等),满足多数需求。
缺点:
延迟时间不灵活
不支持精确到秒级的任意时间延迟(如 7 秒或 3 天),需通过业务层绕道实现(
潜在消息堆积
延时消息存储在特定 Topic(SCHEDULE_TOPIC_XXX),若大量使用且延迟时间较长,可能占用存储资源,影响 Broker 性能。
投递时间误差
延时消息的投递依赖 Broker 定时扫描,可能存在微小延迟(通常毫秒级),对超敏感场景需谨慎。
八,消息挤压问题
消息积压通常由 生产者速率过快 或 消费者处理能力不足 引起。
解决方法:
消费者扩容:如果当前 Topic 的 Message Queue 的数量大于消费者数量,就可以对消费者进行扩容,增加消费者,来提高消费能力,尽快把积压的消息消费玩。添加消费者同时,也要添加队列。
降级处理:跳过非关键消息,或仅处理最新数据(如设置消息TTL)
批量消费:启用批量消费模式,减少网络和事务开销。
修改持久化操作:将同步操作(如写数据库)改为异步(如写入内存队列,由其他线程处理)。
提升消费速度:优化消费者代码(如减少DB操作)/
消息转储:将积压消息转移到其他存储(如HDFS),后续离线处理。
九,死信队列?
死信队列是 RocketMQ 中用于存储无法被正常消费的消息的专用队列。当消息经过多次重试仍无法被消费者成功处理时,RocketMQ 会自动将这些消息转移到死信队列中,避免因单条消息的失败阻塞整个消费流程。
触发条件:
消息在消费者端重试次数达到阈值(默认重试 16 次,超过后进入死信队列)。
消息因业务逻辑问题(如数据格式错误)被消费者主动标记为失败。
设置最大重试次数:
// 消费者设置最大重试次数(默认16)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group");
consumer.setMaxReconsumeTimes(10); // 修改为最多重试10次
这个是官方文档的图片: