Skip to content

消息中间件面试题库 ​

生成时间:2026-05-23 15:55


本轮 消息中间件面试题(带答案) ​

【面试题】1. RabbitMQ的四种Exchange类型有什么区别?分别适用什么场景? ​

【标准答案】

RabbitMQ有四种Exchange,核心区别在于路由规则:

1. Direct Exchange(直连):精确匹配routing key,一对一。适合点对点消息,比如订单系统只给订单队列发消息。

2. Fanout Exchange(扇出):无视routing key,广播到所有绑定队列。适合广播场景,比如用户注册后同时发短信、邮件、积分。

3. Topic Exchange(主题):支持通配符匹配,*匹配一个单词,#匹配多个。适合多条件路由,比如日志系统按级别和模块路由,log.error.#匹配所有error日志。

4. Headers Exchange(头部):匹配消息头属性,性能差,基本不用。

实际选型:90%场景用Direct和Topic,Fanout用于广播,Headers几乎不用。


【面试题】2. Kafka的ISR机制是什么?为什么能保证数据不丢? ​

【标准答案】

ISR是In-Sync Replicas,同步副本集合,是Kafka高可用的核心。

机制原理:

  • 每个Partition有一个Leader和多个Follower
  • ISR里的副本跟Leader保持同步(默认落后不超过一定阈值)
  • 只有ISR里的副本才有资格当选新Leader
  • acks=all时,Leader等ISR所有副本确认后才返回成功

为什么能保证不丢:

  • acks=all + min.insync.replicas=2,至少2个副本写入成功
  • 即使Leader挂了,ISR里还有副本有完整数据
  • 配合unclean.leader.election.enable=false,非ISR副本不能当选Leader

关键配置:acks=all、min.insync.replicas≥2、replication.factor≥3,这三个配置保底数据安全。


【面试题】3. RocketMQ的事务消息是怎么实现的?半消息是什么? ​

【标准答案】

RocketMQ事务消息解决分布式事务问题,核心是"半消息"机制。

半消息:暂不能被消费的消息,暂存在Broker,等本地事务执行成功后才对消费者可见。

完整流程:

  1. Producer发送半消息到Broker(消息状态为"暂不可消费") 2.Broker返回半消息发送成功
  2. Producer执行本地事务
  3. 根据本地事务结果,向Broker发送Commit或Rollback
  4. 如果Commit,消息变为可消费;Rollback则丢弃

关键机制-消息回查:

  • 如果Producer挂了或网络超时,Broker没收到Commit/Rollback
  • Broker会定期回查Producer本地事务状态
  • Producer返回状态后,Broker做对应处理

适用场景:订单创建+库存扣减、支付成功+积分增加等分布式事务场景。


【面试题】4. 消息消费端如何保证幂等性?有几种方案? ​

【标准答案】

消息重复消费是必然的(网络抖动、重试等),消费端必须幂等。

方案一:唯一ID + 数据库去重

  • 每条消息带唯一业务ID(如订单号)
  • 消费前查数据库,已存在则跳过
  • 数据库表加唯一索引,插入失败说明已处理

方案二:唯一ID + Redis去重

  • 消费前用SETNX设置key,设置成功则处理
  • 设置过期时间,避免无限堆积
  • 性能比数据库好,适合高并发

方案三:乐观锁/状态机

  • 消息带版本号或期望状态
  • 更新时加条件:UPDATE order SET status=PAID WHERE id=xxx AND status=UNPAID
  • 影响行数为0说明已处理

方案四:Token机制

  • 业务操作前先申请Token,消费时验证并销毁
  • 适合需要强控制的场景

实际选型:Redis去重性能最好,数据库唯一索引最稳妥,乐观锁最常用。


【面试题】5. 线上出现消息积压,怎么快速处理? ​

【标准答案】

消息积压是线上常见问题,要快速止损。

第一步:定位原因

  • 消费者处理慢?代码有性能问题或下游依赖慢
  • 消费者数量不够?单机消费能力有限
  • 消息量突增?活动或促销导致流量暴涨

第二步:紧急处理

  • 临时扩容消费者:增加消费者实例,提高并发度
  • 批量消费模式:一次拉取多条消息,减少网络开销
  • 降级非核心逻辑:跳过非必要处理,先快速消费
  • 新增临时队列:原有消费者继续处理,新消费者处理积压

第三步:根本解决

  • 优化消费者代码性能
  • 下游依赖做异步化或批量处理
  • 合理规划分区数和消费者数量

关键指标:监控Lag(积压量),设置告警阈值,提前发现。


【面试题】6. Kafka为什么快?零拷贝和顺序写是什么? ​

【标准答案】

Kafka的高性能是架构设计的综合结果,核心有三个原因。

1. 顺序写磁盘

  • 传统磁盘随机写慢,但顺序写可达数百MB/s
  • Kafka的Partition内消息追加写入,全是顺序写
  • 顺序写比随机写快几个数量级

2. 零拷贝(Zero-Copy)

  • 传统数据传输:磁盘→内核→用户→内核→网卡,4次拷贝
  • Kafka用sendfile系统调用:磁盘→内核→网卡,只有2次拷贝
  • 数据不经过用户空间,减少CPU开销

3. 批量与压缩

  • 批量发送,减少网络IO次数
  • 支持GZIP/Snappy/LZ4压缩,减少数据量
  • 生产者批量聚合,消费者批量拉取

总结:顺序写解决磁盘瓶颈,零拷贝解决网络瓶颈,批量压缩解决CPU瓶颈。


【面试题】7. 如何保证消息的顺序性?有几种方案? ​

【标准答案】

消息顺序性分全局有序和分区有序,实现难度不同。

全局有序:

  • 所有消息发到同一个Partition/Queue
  • 只有一个消费者消费
  • 性能差,实际很少用

分区有序:

  • 同一个业务ID的消息发到同一个分区
  • 每个分区只有一个消费者线程
  • 常用方案,性能和顺序性平衡

具体实现(Kafka):

  • 生产者指定Partition Key(如订单ID)
  • 同一订单的消息路由到同一Partition
  • 消费端单线程消费或按Key分发到单线程队列

具体实现(RocketMQ):

  • 发送时指定MessageQueueSelector,按业务ID取模选队列
  • 消费端用MessageListenerOrderly,单线程顺序消费

注意点:

  • 顺序消息不能用多线程消费,会乱序
  • 消费失败要谨慎重试,避免阻塞后续消息

【面试题】8. RabbitMQ的死信队列DLX是什么?怎么用? ​

【标准答案】

死信队列(DLX)是RabbitMQ的消息回收站,处理无法正常消费的消息。

什么情况产生死信:

  1. 消息被NACK或Reject,且requeue=false
  2. 消息TTL过期
  3. 队列满了,新消息被丢弃

如何配置死信队列:

  • 声明业务队列时,设置x-dead-letter-exchange指向死信交换机
  • 设置x-dead-letter-routing-key指定路由键
  • 死信交换机绑定死信队列

实际应用:

  • 失败消息兜底:消费失败的消息进DLX,人工处理或重试
  • 延迟队列:消息设TTL,过期后进DLX,实现延迟消费
  • 消息审计:DLX里的消息记录日志,排查问题

最佳实践:DLX单独用一个Exchange,死信队列配告警,及时处理异常。


【面试题】9. 从生产到消费,全链路如何防止消息丢失? ​

【标准答案】

消息丢失可能发生在三个环节,每个环节都要防护。

生产端防丢:

  • RabbitMQ:开启Confirm模式,waitForConfirms()确认
  • Kafka:acks=all,所有ISR副本确认
  • RocketMQ:同步发送,等待Broker返回
  • 捕获发送异常,重试或落库补偿

Broker端防丢:

  • 开启持久化:消息写入磁盘
  • 配置副本:多副本保证数据安全
  • 刷盘策略:同步刷盘或合理异步刷盘间隔

消费端防丢:

  • 手动确认:业务成功后再ACK
  • 捕获异常:失败不ACK,让消息重新入队
  • 死信兜底:多次重试失败进DLX

关键原则:宁可重复不可丢。配置auto.commit=false,手动提交offset。


【面试题】10. Kafka消费者Group重平衡是什么?有什么问题? ​

【标准答案】

重平衡(Rebalance)是Consumer Group内消费者与分区重新分配的过程。

触发条件:

  • 消费者加入或退出
  • 订阅Topic的分区数变化
  • 消费者心跳超时(默认10s)
  • 消费者处理时间过长(max.poll.interval超时)

重平衡过程:

  1. 所有消费者停止消费,加入Group
  2. 选出Group Leader
  3. Leader分配分区方案
  4. 所有消费者按方案同步分配结果

重平衡的问题:

  • 消费暂停:重平衡期间所有消费者停止消费
  • 重复消费:offset提交不及时,可能导致消息重复
  • 频繁重平衡:消费者频繁上下线导致消费抖动

优化方案:

  • 合理设置session.timeout.ms和heartbeat.interval.ms
  • 单次拉取消息数max.poll.records不要太大
  • 使用静态成员(group.instance.id)减少不必要重平衡
  • 消费逻辑要快,避免超过max.poll.interval.ms

说明:本轮题目覆盖RabbitMQ、Kafka、RocketMQ核心原理,以及幂等性、顺序性、积压处理、全链路可靠性等通用问题,适合面试高频考点。