消息中间件面试题库
生成时间:2026-05-21 22:09
【面试题】1. Kafka的ISR机制是什么?为什么需要ISR?同步延迟怎么处理?
【标准答案】ISR(In-Sync Replicas)是Kafka中与Leader保持同步的副本集合。每个Partition有一个Leader和多个Follower,只有ISR中的副本才有资格被选为新Leader。
为什么需要ISR?
- 纯同步复制:一条消息要所有副本都确认才算写入成功,性能差
- 纯异步复制:Leader挂了可能丢数据
- ISR是折中方案:只要ISR中的副本同步了就认为成功,兼顾性能和可靠性
同步延迟怎么处理?
replica.lag.time.max.ms:默认30秒,超过这个时间没同步的副本会被踢出ISR- 生产者设置
acks=all,消息必须被ISR所有副本确认 - 监控ISR收缩告警,ISR过少时及时排查网络或磁盘问题
【面试题】2. RabbitMQ的四种Exchange类型分别适用什么场景?路由键怎么设计?
【标准答案】四种Exchange类型:
| 类型 | 路由规则 | 适用场景 |
|---|---|---|
| Direct | 精确匹配routing key | 点对点、订单状态通知 |
| Fanout | 广播到所有绑定队列 | 群发通知、缓存刷新 |
| Topic | 通配符匹配(* #) | 多条件过滤、日志分级 |
| Headers | 匹配消息头键值对 | 复杂条件路由(少用) |
路由键设计建议:
- Direct:用业务ID,如
order.created、user.login - Topic:用层次结构,如
order.*.paid、log.# - Fanout:不需要routing key
- 避免routing key过长,影响匹配性能
【面试题】3. RocketMQ的事务消息原理是什么?如何保证分布式事务一致性?
【标准答案】事务消息原理(半消息机制):
- 发送半消息:Producer发一条"半消息"到Broker,消费者不可见
- 执行本地事务:Producer执行本地数据库操作
- 提交/回滚:根据本地事务结果,向Broker发送提交或回滚指令
- 回查机制:如果Broker没收到确认,会定时回查Producer事务状态
如何保证一致性?
- 半消息+本地事务+确认三步是原子的
- 回查机制解决Producer宕机后的事务状态丢失
- 消费端通过幂等性保证不重复消费
适用场景:
- 跨系统的最终一致性事务
- 订单创建+库存扣减+积分发放等链路
【面试题】4. 消息积压了怎么处理?生产端和消费端分别怎么优化?
【标准答案】消息积压应急处理四步走:
- 快速定位:看监控面板,确认是哪个Topic/队列积压
- 临时扩容:增加Consumer实例数,提升消费速度
- 批量消费:改为批量拉取+批量处理
- 降级策略:非核心消息丢弃或延迟处理
生产端优化:
- 限流:控制消息发送速率
- 压缩:减少网络传输量
- 批量发送:Kafka天然支持,RabbitMQ用批量confirm
消费端优化:
- 增加分区数(Kafka)或队列数(RabbitMQ)
- 提高并发度:Kafka的
max.poll.records,RabbitMQ的prefetch - 异步处理:消息接收入库,后台异步消费
- 跳过积压消息:极端情况下,重置offset到最新
【面试题】5. Kafka的零拷贝是怎么实现的?为什么比传统IO快?
【标准答案】传统IO流程(4次拷贝,4次上下文切换): 磁盘 → 内核缓冲区 → 用户缓冲区 → 内核Socket缓冲区 → 网卡
Kafka零拷贝(sendfile,2次拷贝,2次切换): 磁盘 → 内核缓冲区 → 网卡
实现原理:
- Linux的
sendfile系统调用,数据直接从文件描述符传输到Socket - DMA直接传输,绕过用户空间
- Kafka消息存放在PageCache,发送时直接从内存到网络
为什么快?
- 减少数据拷贝次数(4次→2次)
- 减少上下文切换(4次→2次)
- 减少CPU参与,DMA直接完成传输
配合顺序写:
- Kafka消息顺序追加到日志文件
- 磁盘顺序写速度可达600MB/s,远超随机写
【面试题】6. RabbitMQ如何实现延迟队列?有哪些方案?
【标准答案】方案一:TTL + 死信队列(DLX)
消息 → 普通队列(设置TTL)→ 过期 → 死信队列(DLX)→ 消费者- 消息设置TTL,过期后自动进入死信队列
- 缺点:先进先出,第一个消息TTL最长会阻塞后面的消息
方案二:rabbitmq_delayed_message_exchange插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange- 消息带上
x-delay头,延迟指定时间后路由到队列 - 优点:消息独立延迟,互不阻塞
- 缺点:需要安装插件
方案三:外部定时任务调度
- Redis的ZSet + 定时扫描
- XXL-JOB等定时任务框架
- 适用:延迟任务量大且复杂
选型建议:
- 简单延迟:TTL+DLX
- 灵活延迟:插件
- 大规模延迟任务:Redis+定时任务
【面试题】7. 消费端幂等性如何设计?有哪些去重方案?
【标准答案】幂等性概念: 同一条消息被消费多次,结果与消费一次相同。
去重方案:
| 方案 | 实现方式 | 优点 | 缺点 |
|---|---|---|---|
| 唯一ID+数据库 | 消息ID做唯一索引 | 简单可靠 | 性能差 |
| 唯一ID+Redis | SETNX去重 | 高性能 | 依赖Redis |
| 乐观锁 | 版本号更新 | 无额外存储 | 需业务支持 |
| 状态机 | 订单状态流转 | 业务语义强 | 适用场景有限 |
推荐方案:唯一ID + Redis + 数据库兜底
// 1. Redis去重
if (redis.setnx(msgId, "1", 24h)) {
// 2. 数据库唯一索引兜底
try {
process(msg);
} catch (DuplicateKeyException e) {
// 已处理过,忽略
}
}关键点:
- 消息必须有唯一ID(Kafka的offset + partition + topic组合,RocketMQ的msgId)
- Redis过期时间要大于消息处理周期
- 数据库唯一索引是最后一道防线
【面试题】8. RabbitMQ和Kafka的架构差异是什么?选型时怎么选?
【标准答案】架构对比:
| 维度 | RabbitMQ | Kafka |
|---|---|---|
| 设计理念 | 智能路由Broker | 日志存储系统 |
| 消息模型 | Queue + Exchange | Topic + Partition |
| 消息存储 | 内存为主 | 磁盘顺序写 |
| 消费模式 | 推模式(Push) | 拉模式(Pull) |
| 消息确认 | ACK/NACK | Offset提交 |
| 吞吐量 | 万级/秒 | 十万~百万级/秒 |
| 延迟 | 微秒级 | 毫秒级 |
| 消息堆积 | 内存有限 | 磁盘海量存储 |
选型建议:
选RabbitMQ:
- 消息量小(<10万/秒)
- 需要复杂路由规则
- 要求延迟极低
- 需要事务消息、延迟队列
选Kafka:
- 消息量大(>10万/秒)
- 需要消息回溯、持久化
- 日志收集、大数据管道
- 流式计算(Kafka Streams)
RocketMQ:
- 阿里出品,适合电商场景
- 事务消息、延迟消息功能强
- 国内社区活跃
【面试题】9. Kafka的Consumer Group重平衡协议是什么?如何避免重平衡风暴?
【标准答案】重平衡协议: 当Consumer Group中消费者变化或Topic分区数变化时,重新分配分区给消费者的过程。
触发条件:
- 新消费者加入
- 消费者宕机或主动退出
- Topic分区数变化
- 消费者心跳超时(
session.timeout.ms)
重平衡流程:
- 消费者请求加入Group
- 选出Coordinator(Group Leader)
- Leader分配分区方案
- 所有消费者同步新方案
- 开始消费
重平衡风暴: 频繁重平衡导致消费暂停,吞吐量骤降。
如何避免?
- 增大
session.timeout.ms(默认10s → 30s+) - 增大
max.poll.interval.ms(处理时间不足会触发重平衡) - 减少Consumer数量变化(容器化环境固定实例数)
- 使用静态成员(
group.instance.id)
监控告警:
- 监控重平衡次数和耗时
- 消费延迟告警
【面试题】10. 如果Kafka消息丢失了,怎么排查?全链路怎么保证不丢?
【标准答案】全链路消息丢失风险点:
| 环节 | 风险 | 解决方案 |
|---|---|---|
| 生产者 | 发送失败未确认 | acks=all + 重试 |
| Broker | 副本未同步 | min.insync.replicas=2 |
| Broker | 刷盘前宕机 | unclean.leader.election.enable=false |
| 消费者 | 处理失败但提交offset | 先处理再提交 |
排查步骤:
生产端排查:
- 检查是否有发送失败日志
- 确认是否开启
acks=all - 检查重试次数和超时配置
Broker端排查:
- 检查ISR列表是否正常
min.insync.replicas配置- 磁盘空间、网络抖动
消费端排查:
- 检查offset提交时机
- 是否有消费异常但提交了offset
最佳实践配置:
# 生产者
acks=all
retries=3
enable.idempotence=true
# Broker
min.insync.replicas=2
unclean.leader.election.enable=false
# 消费者
enable.auto.commit=false
# 手动提交offset总结一句话: 生产者确认、Broker多副本同步、消费者先处理再提交。
本轮题目覆盖: ISR机制、Exchange路由、事务消息、消息积压处理、零拷贝原理、延迟队列、消费幂等、架构选型、重平衡协议、消息丢失排查