参考资料:https://cloud.tencent.com/developer/article/2335397
https://www.cnblogs.com/hahaha111122222/p/18457859
消息队列是大型分布式系统不可缺少的中间件,也是高并发系统的基石中间件
消息队列
消息队列 Message Queue
消息队列是利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的构建。
消息队列主要解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性的系统架构。目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等。
消息通讯;应用解耦;异步处理
-
模块之间不需要直接通知,而是通过消息队列。
-
业务可并行,并且不需要阻塞等待处理的结果。
模块之间本身是可以直接调用的,但是这样请求是同步的(需等待被请求的模块处理完才能拿到结果),耦合度高,而且返回失败后请求方还得做其他处理。
但是使用消息队列,直接把请求交给消息队列,至于什么时候处理,不关心,处理结果另外收集即可。
流量削峰
像秒杀活动,一般流量过大会导致应用挂掉。
而应用服务通过消息队列接收消息,消息队列就可以进行请求控制,比如可以设置最大接收数目,抛弃多余请求。
常用消息队列比较
特性 | Kafka | RocketMQ | RabbitMQ | ActiveMQ |
---|---|---|---|---|
单机吞吐量 | 10万级(极限可更高) | 10万级 | 万级(性能相对较低) | 千级到万级(性能一般) |
开发语言 | Scala(核心),Java | Java | Erlang | Java |
高可用 | 分布式,依赖 ZooKeeper(新版可选) | 分布式,支持多副本 | 支持集群和镜像队列(主从) | 支持主从、副本集群 |
消息延迟 | ms 级(堆积时可能升高) | ms 级 | us 级(低延迟) | ms 级 |
消息丢失 | 理论上不会丢失(开启 ACK 和持久化) | 理论上不会丢失(支持多副本 + 持久化) | 配置合理下可靠,默认情况存在丢失风险 | 默认持久化支持较弱,存在一定丢失可能 |
消费模式 | 拉取模式 | 推+拉模式 | 推+拉模式 | 推+拉模式 |
持久化 | 文件系统(顺序写入,性能高) | 文件为主,内存缓存 | 内存、磁盘,可接入数据库 | 文件为主 |
支持协议 | 自定义协议 | 自定义协议 | AMQP、XMPP、SMTP、STOMP | AMQP、MQTT、OpenWire、STOMP 等多协议支持 |
社区活跃度 | 高(Confluent 等活跃) | 中(阿里主导,国内活跃) | 高(社区大,文档丰富) | 较低(活跃度不如前几者) |
管理界面 | 第三方工具(如 Kafka Manager、Control Center) | 官方控制台,功能丰富 | 自带 Web 管理界面,功能强 | 自带 Web 控制台,功能一般 |
部署难度 | 中(原生依赖 ZooKeeper,需调优) | 低(部署简单,结构清晰) | 低(配置灵活,上手快) | 低(部署最为简单) |
部署方式 | 独立运行 | 独立运行 | 独立运行 | 独立运行或嵌入到应用中 |
成熟度 | 成熟(大规模使用,如 LinkedIn) | 成熟(阿里巴巴开源,国内支持好) | 成熟(广泛使用,AMQP 标准) | 成熟(历史悠久,但逐渐被替代) |
综合评价 | ✅ 优点:超高吞吐量、支持大数据处理场景; ❌ 缺点:延迟可能高,学习曲线略陡。 | ✅ 优点:性能强,稳定可靠,中文文档多; ❌ 缺点:协议不标准,兼容性差。 | ✅ 优点:部署简单,协议标准,路由机制灵活; ❌ 缺点:吞吐量低,性能瓶颈明显。 | ✅ 优点:历史悠久,协议支持多,语言兼容广; ❌ 缺点:社区活跃度低,可靠性一般。 |
精简:
- Kafka 消费者只能拉取:
Kafka 是面向高吞吐、高并发、海量数据设计的,消费者主动拉更好控制消费速率。所以 Kafka 天然支持**“重复消费”和“反复消费”**,这是和 MQ 类不同的。 - RocketMQ 自带 Nameserver 组件,做服务发现和路由,不需要 ZooKeeper。
而 Kafka 必须依赖 ZooKeeper 管理元数据(比如 topic、分区、broker 状态等),所以Kafka 配置更繁琐,不能“开箱即用”,而且稍不注意就会影响数据均衡和消费效果。(不过 Kafka 社区现在慢慢往去 ZooKeeper 化发展) - RabbitMQ 支持 AMQP 协议,核心设计就是围绕交换机(Exchange)进行消息路由,因此它的路由能力非常灵活、丰富。
而 RocketMQ 仅支持基于主题+tag 的简单分类,路由能力较弱,更偏向主题订阅,业务需要自己拆 topic 。 - 可靠性:
Kafka:持久化存储,PageCache+磁盘,副本同步。
RocketMQ:持久化存储,CommitLog 确认后落盘。消费进度管理、重试、死信,保障较强。(可靠性和性能平衡较好,企业用多)
RabbitMQ:持久化存储,ACK 后落盘。支持重试,死信队列保障
Kafka
Kafka 的定位是分布式日志系统,消息持久化、顺序、可回溯,是核心能力。
至于消息什么时候被消费,是否重复消费,是否幂等,怎么做消息回溯,这些通通交给业务自己决定。
Kafka 更偏向于“高吞吐日志系统”,适合大数据、日志、流式处理场景。
一台 kafka服务器就是一个 broker。(代理,经纪人)
一台服务器里的每个消息队列叫做 Topic
Partition:分区,分区内部会有序,即需按写入顺序读。
一个 topic 可以划分为多个 partition,每个 partition 都可以在不同的 broker 上运行,支持并发写入和消费。【横向扩展性能】
高可用 - “副本机制”:对于每个partition 配置多个 replica(副本),多个线程都进行相同的读写操作,这样一个线程意外挂了,其他线程仍能正常处理。
RocketMQ
RocketMQ是阿里巴巴开源的一个消息中间件,在阿里内部历经了双十一等很多高并发场景的考验,能够处理亿万级别的消息。2016年开源后捐赠给Apache,现在是Apache的一个顶级项目。
-
消费顺序:如果想按某个业务 ID 顺序消费,Kafka需要自定义key。
而RocketMQ 明确支持 顺序消息机制,使用其工具,就能轻松做到“业务 ID 保证顺序消费”。 -
重试机制:Kafka 原生没有重试机制,要么靠消费端自己实现,要么引入外部机制。
RocketMQ 提供:- 消费失败自动重试(延迟重试机制)
- 死信队列(DLQ):重试多次后仍失败的消息可转入死信队列,避免消息丢失。
-
消费绑定:RocketMQ 的消费者可以根据Tag进行消息过滤,也支持自定义属性过滤。消息过滤 在Broker端实现。
Kafka 没有 tag 概念,只能通过 topic + key + 自定义字段实现 -
调试监控:对于业务调试/监控,RocketMQ 更友好:
RocketMQ 支持 消息轨迹跟踪(可记录消息从发送到消费的全过程)
Kafka 不提供这类追踪功能,需要额外接入链路追踪系统如 Zipkin/SkyWalking -
延时消息机制
RocketMQ 支持 定时/延时消息(比如延迟 5 秒、10 分钟后投递)
Kafka 没有原生延迟投递功能,延时处理必须靠业务自己处理(例如定时轮询 + 状态判断)
Nameserver
Nameserver 是 RocketMQ 中的“注册中心 + 路由发现中心”。
作用:“电话本”
Broker 启动时,向 Nameserver 注册自己的信息(IP、端口、Topic 等)
Producer / Consumer 通过 Nameserver 获取最新的 Broker 路由信息,知道消息该发/该拉去哪里。
RabbitMQ
概念名称 | 含义 |
---|---|
Producer | 生产者,负责发送消息 |
Consumer | 消费者,负责从队列中取消息 |
Queue | 队列,消息实际存储的地方,Consumer 从队列中取消息 |
Exchange | 交换机,负责接收消息,并根据规则(绑定关系、RoutingKey)【路由】到队列 |
Binding | 绑定,交换机和队列之间的【映射规则】,决定哪些消息能进哪个队列 |
Routing Key | 路由键,生产者发消息时指定的关键字,决定消息流向哪个队列 |
Virtual Host | 虚拟主机,【隔离】不同业务的逻辑空间,类似数据库里的库名 |
Exchange 多种交换机类型:direct、topic、fanout扇出即广播 等,路由非常灵活,支持多绑定、模糊匹配、广播等多种模式,适合复杂业务场景。
类型 | 路由规则说明 | 应用场景 |
---|---|---|
Direct | 按照 RoutingKey 【完全匹配】,精准投递 | 一对一精准消息 |
Fanout | 【广播】模式,忽略 RoutingKey,所有绑定的队列都收到消息 | 广播消息通知 |
Topic | 按通配符匹配 RoutingKey,支持 * / # 模糊匹配 | 订阅模式,分类更细 |
( Headers) | 根据消息头属性进行路由,而不是 RoutingKey | 特殊需求较少用 |
工作流程:
- Producer 把消息交给 Exchange。
- Exchange 根据 RoutingKey + Binding 决定把消息投递到哪个 Queue。
- Consumer 从 Queue 拿消息消费。
RabbitMQ 是对 AMQP 协议支持最完整、最标准的消息队列。
AMQP
AMQP,Advanced Message Queuing Protocol 高级消息队列协议
它规定了消息队列该如何通信,包括:
- 消息如何传递
- 消息格式
- 消息的路由逻辑
- 消息的确认机制
AMQP 的目标是:跨语言、跨平台,让不同厂商的消息中间件也能互通。
缺点:
消息顺序性弱 不保证严格顺序(不像 Kafka 按分区顺序写入消费)
性能比 Kafka、RocketMQ 弱,适合业务耦合较多的企业应用场景