目录
消息队列面试题
以下是 消息队列(Message Queue, MQ) 相关的常见面试题,涵盖 基本概念、应用场景、性能优化、故障处理 等方面。
一、消息队列基础
1.消息队列(MQ)是什么?为什么要使用它?
消息队列(Message Queue, MQ) 是一种用于异步通信的组件,允许不同的应用或服务之间通过发送和接收消息进行交互。 它的主要作用包括:
-
解耦:生产者和消费者相互独立,降低系统耦合度。
-
削峰填谷:应对流量高峰,防止系统过载。
-
异步处理:加快请求响应,提高系统吞吐量。
-
可靠性保障:保证消息的持久化和可靠投递,防止数据丢失。
2.消息队列的核心组成部分有哪些?
MQ 主要由以下几个部分组成:
-
生产者(Producer):发送消息的一方。
-
消息代理(Broker):负责存储、路由和分发消息。
-
消费者(Consumer):接收并处理消息的一方。
-
消息队列(Queue):存储待处理的消息。
-
主题(Topic):用于发布-订阅模式,生产者发布消息,多个消费者订阅消息。
-
交换机(Exchange)(RabbitMQ 特有):决定消息如何路由到队列。
3.消息队列的应用场景有哪些?
解耦:
-
订单系统 -> 支付系统
-
生产者只负责发送消息,不需要关心消费者是否成功处理。
削峰填谷(流量控制):
-
高峰期时,将大量请求存入队列,后台慢慢处理,避免系统崩溃。
-
例子:秒杀系统
异步处理:
-
业务流程拆分,提高系统吞吐量。
-
例子:用户注册后,邮件/短信通知异步发送。
流量削减(限流):
-
消息队列+消费者限流,防止流量突然暴增压垮数据库。
日志收集:
-
通过 Kafka 采集日志数据,存入大数据系统分析。
4.如何选择合适的消息队列?
高吞吐场景:Kafka > RocketMQ
可靠性要求高(金融、订单): RabbitMQ、RocketMQ
事务支持(保证消息一致性): RocketMQ > RabbitMQ
日志收集、大数据:Kafka > Pulsar
跨平台、传统系统:ActiveMQ
5.如何保证消息的可靠传输(防止丢失消息)?
消息传输涉及 生产者、Broker、消费者 三个环节,每个环节都可能丢失消息,因此需要采取相应的措施来保证消息的可靠性。
1️⃣ 生产者 -> 消息确认机制(确保消息投递成功)
生产者需要确保消息成功发送到 Broker,可以使用发送确认机制:
-
同步发送(Sync Send):生产者等待 Broker 确认消息接收,保证消息可靠投递,但会增加延迟。
-
异步发送(Async Send):性能较高,但可能丢失消息,需要重试机制。
-
发送失败重试:生产者发送消息失败时,进行重试或持久化存储后再发送。
RabbitMQ 提供 Publisher Confirms(发布者确认) 机制,确保消息被正确投递到 Broker。
2️⃣ Broker -> 持久化存储(确保消息不会丢失)
消息持久化 确保 Broker 在宕机或崩溃后能够恢复数据。
方案:
-
RabbitMQ
-
开启 消息持久化(
deliveryMode=2
,确保消息写入磁盘)。 -
持久化队列(
durable=true
),确保队列数据存储到磁盘。
-
-
Kafka
-
日志存储(WAL 机制):消息写入磁盘后才算投递成功。
-
副本机制(ISR):确保数据被多个副本存储,防止丢失。
-
-
RocketMQ
-
采用刷盘机制(同步刷盘/异步刷盘)提高可靠性。
-
3️⃣ 消费者 -> 幂等性 & 手动 ACK(防止消息丢失和重复消费)
消费者处理消息后,需要确保消息不会丢失或重复处理。
消息丢失
-
手动 ACK:消费者处理完业务后,手动确认(
ACK
)消息,防止消费失败导致数据丢失。 -
消息重试:消费失败后,消息重新入队或重试队列。
消息重复
-
幂等性设计:
-
唯一 ID(例如订单 ID)记录已处理消息,防止重复消费。
-
使用 数据库唯一约束 或 Redis SET 记录消费状态。
-
-
RabbitMQ:开启 ACK 机制(
autoAck=false
),确保消息正确消费后才从队列删除。 -
Kafka:通过 消费者位移(Offset)管理,防止重复消费。
-
RocketMQ:事务消息,确保消息幂等处理。
6.如何防止消息重复消费?
消息去重 + 幂等性
-
Redis
-
使用 SETNX(分布式锁) 确保相同消息不被重复处理。
-
记录 消费的消息 ID,如果已消费,则丢弃。
-
-
数据库
-
通过 唯一索引(如订单号)避免重复插入数据。
-
-
Kafka
-
使用事务消费者,确保消息消费后才提交位移(Offset)。
-
7.如何防止消息积压?
消息积压(消息堆积在队列中)可能会导致系统崩溃,需要及时处理:
✅ 增加消费者数量:提高消费能力,减少积压。 ✅ 消费分区(Kafka、RocketMQ):使用多个分区,让多个消费者并行处理。 ✅ 限流(Rate Limit):
-
采用 漏桶算法、令牌桶算法,限制消息消费速率。
-
适用于 消息突增 场景,避免消费者过载。 ✅ 消费重试队列(Dead Letter Queue, DLQ):
-
RabbitMQ/Kafka 支持死信队列,将失败消息转移到死信队列中,避免影响正常队列。