消息队列学习计划 - 阶段三:面试高频问题

张开发
2026/4/14 1:34:27 15 分钟阅读

分享文章

消息队列学习计划 - 阶段三:面试高频问题
消息队列学习计划 - 阶段三面试高频问题目标准备所有 MQ 相关面试问题覆盖基础到进阶能应对字节/腾讯等大厂面试预计周期1 周每天 1-2 小时以记忆和模拟为主面试问题分类类别问题数量难度覆盖公司基础概念5 题⭐字节/腾讯/美团进阶原理8 题⭐⭐字节/腾讯/阿里项目相关5 题⭐⭐字节/腾讯必问系统设计4 题⭐⭐⭐腾讯/阿里/字节核心部门联级追问不限⭐~⭐⭐⭐视回答情况延伸Part 1基础概念5 题要求能用自己的话解释清楚不要求背答案Q1为什么需要消息队列不用会怎样回答思路自己的话版不用 MQ 的问题系统 A 直接调用 B两个系统强耦合。A 升级改接口B 跟着改秒杀场景 10 万人下单后端只能处理 1 万其余直接崩下单后要发短信/邮件/通知串行执行用户等半天用 MQ 的价值解耦A 只管发消息B/C/D 各接各的互不影响削峰10 万请求先入队列后端慢慢处理不崩异步下单 500ms → 发MQ → 100ms 返回短信通知异步处理追问如果不用 MQ还有什么替代方案直接 RPC无法削峰耦合数据库表做队列轮询消耗资源不实时本地文件 异步线程无法分布式不可靠Q2Kafka 为什么能做到高吞吐回答思路六个点每个记住一句话顺序写入写磁盘永远在末尾追加顺序 I/O 速度接近内存零拷贝sendfile 系统调用数据从磁盘到网卡跳过人态绕过用户缓冲区减少 CPU 拷贝批量处理消息攒一批再发送/消费减少网络往返次数页缓存Page Cache利用 Linux 内存缓存热数据不需要每次都读磁盘稀疏索引.index文件按固定间隔建索引不是每条消息都建减小索引体积多分区并行Partition 之间相互独立磁盘并行写入一个综合回答30 秒版Kafka 高吞吐主要靠四点磁盘顺序写入避免随机 I/Osendfile 零拷贝减少 CPU 拷贝和数据复制利用 Linux Page Cache 缓存热数据消息批量发送和压缩减少网络开销。再加上多 Partition 分区并行处理吞吐自然就上去了。追问零拷贝具体怎么实现的和传统 I/O 有什么区别传统 I/O4次拷贝磁盘→内核缓冲区→用户缓冲区→Socket缓冲区→网卡零拷贝3次拷贝 1次系统调用磁盘→内核缓冲区sendfile→网卡mmap映射文件到用户空间跳过一次拷贝适合读多写少场景Q3Kafka 的 ACK 机制有几种生产环境用哪个三种 ACKsACK含义可靠性性能适用场景acks0发出去就不管了最低可能丢消息最高日志采集、监控数据丢了无所谓acks1等 Leader 写入成功中等Leader 挂会丢中等一般业务场景默认配置acks-1/all等 ISR 所有副本都写入最高最低金融、订单等核心业务生产环境建议一般业务acks1配合重试机制retries3核心业务acks-1配合min.insync.replicas2纯日志/监控acks0追求最高吞吐追问ISR 是什么ISRIn-Sync Replicas是当前和 Leader 保持同步的副本集合。只有在 ISR 里的副本才算活着的Leader 选举只从 ISR 里选。Q4消息丢失了怎么办从哪几个环节入手三个丢消息的环节生产者 → Kafka Broker → 消费者 环节1 环节2 环节3环节1生产者发送失败原因网络抖动、Broker 无响应解决acks-1retries3 异步回调检查发送结果兜底本地持久化失败后补偿重发环节2Broker 持久化失败原因Follower 未同步完成时 Leader 挂了解决acks-1replication.factor3min.insync.replicas2环节3消费者处理时崩溃原因处理完还没提交 offset 就崩了解决手动提交 offsetenable.auto.commitfalse处理完业务逻辑再提交或者业务处理和 offset 提交放在同一个事务里一个综合回答消息丢失有三个环节每个环节都要处理。生产者端用acks-1和重试Broker 端配置多副本和 ISR消费者端手动提交 offset确保业务处理完再提交。核心思路是在架构上做冗余在代码上做幂等。Q5如何保证消息不重复消费幂等性什么时候会重复消费生产者超时重试同一条消息发了两遍消费者处理完、提交 offset 前崩溃重启后重复消费解决方案三层防线1. 生产者幂等源头控制开启幂等性enable.idempotencetrueKafka 自动给每条消息加唯一 producer.id sequenceNumberBroker 会丢弃重复序列号的消息2. 消费者幂等消费端兜底数据库唯一索引消费前先查库有记录说明处理过跳过Redis 去重消费前先 SET NX key过期时间设长一点业务去重消息中带唯一 ID消费逻辑判断是否处理过一个综合回答幂等性要分两层做。生产者端开启 Kafka 自带的幂等性enable.idempotencetrue从源头防止重复发送。消费端做业务层去重用 Redis 的 SETNX 或者 MySQL 的唯一索引来保证每条消息只处理一次。两者结合基本不会出现重复消费问题。Part 2进阶原理8 题Q6消费者 Rebalance 是什么什么时候触发如何优化Rebalance 定义Consumer Group 中 Consumer 数量变化时加入/离开/崩溃重新分配 Partition 的过程。触发条件Consumer 重启Consumer 处理超时未发心跳session.timeout.ms触发Consumer 主动离开调用 unsubscribeConsumer 数量超过 Partition 数多余的 Consumer 空闲Rebalance 过程三个阶段JOIN_GROUP所有 Consumer 加入组选举出 Group LeaderSYNC_GROUPGroup Leader 制定分区分配方案同步给所有 ConsumerHEARTBEAT正常消费定期心跳维持组成员关系Rebalance 风暴问题大量 Consumer 同时 join/leave导致每次 Rebalance 期间所有 Consumer 停止消费服务短暂不可用优化方案session.timeout.ms设置合理不要太短建议 10s 以上heartbeat.interval.ms设为 session.timeout 的 1/3减少 Consumer 频繁重启Consumer 处理逻辑要快避免心跳超时追问Partition 数和 Consumer 数的关系Partition 数决定最大并发消费数。Consumer 数量超过 Partition 数后多余的 Consumer 空闲。所以 Partition 数要提前规划好不要太少也不要太多。Q7Kafka 的 Topic 删除是立即删除吗日志何时清理两种清理策略1. delete 策略默认超过retention.ms或retention.bytes阈值后标记删除不是立即删除由后台线程定时清理2. compact 策略同一 key 的消息只保留最新一条用于状态存储如数据库变更日志保证每个 key 至少有一条有效消息清理时机日志段Log Segment合并时才真正删除旧文件不是按时间精确清理有一定延迟Q8Kafka 的 Leader 选举过程Controller 是什么Leader 选举分区级当 Leader 所在的 Broker 挂了从 ISR 列表中选择一个 Follower 成为新 Leader如果 ISR 为空取决于unclean.leader.election.enablefalse默认不允许从非 ISR 选举牺牲可用性保证一致性true允许从非 ISR 选举牺牲一致性保证可用性Controller控制器集群中只有一个 Controller通过 ZooKeeper 选举Controller 职责管理分区 Leader 选举感知 Broker 上下线管理 Topic 创建/删除Controller 挂了怎么办ZooKeeper 重新选举新 Controller 立即接管追问选举过程中服务会中断多久Leader 切换通常在毫秒级完成。但切换期间发往该 Partition 的请求会短暂失败新版 Java Client 会自动重试。实际用户感知到的中断通常在 100ms 以内。Q9Kafka vs RabbitMQ 的区别如何选型对比维度KafkaRabbitMQ吞吐量极高百万级 QPS中等万级 QPS延迟低毫秒级较低毫秒到秒级消息顺序单 Partition 内有序队列内有序消息可靠性可配置ACK机制支持 Publisher Confirm消费模式Pub/Sub消费组P2P Pub/Sub功能丰富度简单日志型丰富交换机/路由/死信多租户支持支持适用场景日志采集、实时流处理业务消息、任务队列、复杂路由选型建议选 Kafka高吞吐场景、日志收集、流处理、需要分区并行选 RabbitMQ业务消息、复杂路由多交换机、需要丰富的消息特性延迟队列、优先级队列两者也可以同时用Kafka 做日志/事件流RabbitMQ 做业务消息Q10Kafka 如何实现消息顺序性三个层次的顺序保证1. Kafka 单 Partition 内有序Partition 级同一 Partition 内的消息按 offset 顺序消费保证同一条生产者发送的多条消息按顺序到达消费者2. 全局顺序单 Partition 单 ConsumerTopic 只有 1 个 Partition只有 1 个 Consumer代价失去了并行处理能力3. 业务层面的局部有序推荐按业务 key如 user_id哈希到同一 Partition保证同一用户的操作有序不同用户的操作可并行处理一个回答Kafka 单个 Partition 内是有序的。如果需要全局有序可以设置单 Partition但会失去并行能力。更常见的做法是按业务 key比如用户 ID路由到同一个 Partition保证同一用户的操作有序不同用户之间并行处理。这是业务和性能的平衡。Q11Kafka 消息积压了怎么办原因分析Consumer 消费速度 Producer 发送速度Consumer 处理太慢Consumer 挂了没有消费Partition 数量太少并发度不够解决方案短期应急增加 Consumer 实例消费端水平扩展增加 Consumer 线程数单实例内并行增加 Partition 数配合增加 Consumer长期优化优化 Consumer 处理逻辑减少数据库查询、加缓存、批量处理消费者端加监控提前发现积压趋势生产端限流避免突发流量追问Partition 数量能调吗可以增加kafka-topics --alter但不能减少。减少 Partition 需要删除整个 Topic 后重建。Q12如何设计一个消息延迟投递系统方案一时间轮Redis ZSet / Kafka 单 Partition 按时间戳排序把延迟消息写到 Redis ZSetscore 执行时间戳 后台线程轮询 ZSetscore 当前时间戳 的消息取出来发送方案二Kafka 延迟消费者推荐在你项目里用这个延迟消息发到 DelayTopicTTL延迟时间 TTL 过期后消息落入真实 Topic Consumer 从真实 Topic 消费方案三RabbitMQ 延迟插件消息设置x-delay头指定延迟时间延迟到期后自动进入队列方案四多级时间轮你的内存池项目就是时间轮同一个思路用你写过的时间轮数据结构实现延迟队列可以作为面试亮点你不仅用过时间轮还自己实现过追问Redis ZSet 做延迟队列有什么缺点单个 Redis 实例有性能瓶颈不支持消息持久化Redis 挂了消息丢失多 Consumer 时 ZSet 的 pop 操作需要加锁。Q13如果 Kafka 集群整体挂了怎么办这是一个灾难恢复问题考察架构设计能力。预防措施多 Broker 部署 多副本replication.factor 3跨机架/跨 AZ 部署不同机房acks-1min.insync.replicas2定期检查 ISR 健康状态恢复步骤检查 ZooKeeper / KRaft 状态确认 Controller 存活定位哪些 Broker 挂了尝试重启恢复如果 Broker 无法恢复检查哪些 Partition 的 Leader 不可用手动触发 Leader 选举如果配置允许unclean.leader.election消费者从上次提交的 offset 继续消费可能有小部分消息需要补偿处理降级方案MQ 不可用时Producer 端本地缓存消息服务降级关闭非核心功能优先保证核心链路告警Kafka 挂了应该有监控告警通知到人Part 3项目相关5 题基于你在阶段三完成的项目提前准备好回答Q14你们项目的 Kafka 吞吐量是多少怎么测的回答模板我用 Kafka 自带的kafka-producer-perf-test工具测的。单 Producer 异步发送record 大小 1KBacks1吞吐量达到5万条/秒。Consumer 端单线程消费处理能力约3万条/秒。主要瓶颈在 MySQL 批量写入Consumer 加了本地缓冲后提升到5万条/秒。追问瓶颈在 MySQL 的话怎么优化批量写入攒 100 条再 INSERT读写分离写 MySQL 主库读从库分库分表按时间或业务维度分换成 TiDB 或 ClickHouseQ15如果你的 Kafka Consumer 崩溃了消息会丢失吗结合你的项目设计回答我在 Consumer 端做了两层保护。第一手动提交 offset业务处理成功后才提交。第二用 Redis 记录已处理消息的 ID消费前先查重。这两层保证了即使 Consumer 崩溃重启后要么从上次 offset 继续可能重复消费要么跳过已处理的消息幂等消费。不会丢消息。追问手动提交 offset 会不会更慢不会。我用的是异步提交commitAsync提交 offset 和处理下一批消息是并行的不阻塞消费。只有在 Consumer 退出时才用同步提交commitSync确保最后一批消息的 offset 被正确提交。Q16你的项目为什么选 Kafka 而不是 RabbitMQ结合你的技术栈和场景回答主要有两个原因。第一我项目需要高吞吐日志数据量很大每秒几千条Kafka 的吞吐远高于 RabbitMQ更适合这个场景。第二我的项目是日志分析需要按时间范围查询消息Kafka 的 Log Segment 结构和稀疏索引更适合。而 RabbitMQ 更适合业务消息的复杂路由我的场景用不到。Q17Kafka 和你已有的 Reactor 框架有什么区别和联系这是 C 后端专属问题展示你的技术融合能力本质上两者的设计思想是相通的。Kafka Broker 的网络层是 Java NIO 实现的 Reactor 模式——一个 Selector 监听多个连接 Channel有事件就分发给 Handler 处理。我的 C Reactor 框架也是这个思路只是实现语言不同。区别在于Kafka 的 Reactor 是单 Reactor 多线程 Handler一个线程处理多个连接而我的框架是多 Reactor主从 Reactor 线程池。Kafka 为了保持高吞吐做了批量处理和零拷贝优化我在网络框架里也可以借鉴 Kafka 的批量发送思路做进一步优化。Q18你的消息队列项目遇到过什么困难怎么解决的提前准备好 1-2 个真实遇到的困难困难一Consumer 消费速度跟不上现象压测时消息开始积压消费延迟越来越高。分析用kafka-consumer-groups --describe发现 Consumer CPU 使用率 100%瓶颈在业务处理逻辑太慢每次消费都要查 MySQL。解决加了 Redis 本地缓存热点数据MySQL 查询减少 80%同时增加 Consumer 线程数吞吐量翻倍。困难二Rebalance 时服务短暂不可用现象Consumer 重启时会有一小段时间所有分区重新分配这期间服务中断。分析Rebalance 触发期间所有 Consumer 停止消费新 Consumer 加入时旧 Consumer 需要放弃已有分区。解决尽量避免频繁重启 Consumer调整session.timeout.ms到 30 秒减少误触发将非核心功能拆出去用独立 Consumer。Part 4系统设计4 题Q19如何设计一个每天 10 亿消息的日志收集系统架构设计分层日志源App Server ↓fluentd/filebeat Kafka 集群100 Broker1000 Partition ↓ 消费者集群100 Consumer ↓ 存储层HDFS / ES / ClickHouse ↓ 查询 / 分析平台Grafana / Kibana关键设计点分区策略按服务名 日期分区方便按时间范围查询副本配置replication.factor3min.insync.replicas2数据保留7 天热数据存 Kafka超过的进入冷存储HDFS消费者分组多个 Consumer Group 分别做统计/存储/告警容错Consumer 挂了自动 Rebalance数据不丢Kafka 集群规划消息大小 1KB每天 10 亿条 → 约 10TB/天副本 3 份 → 30TB/天 → 7 天约 210TBBroker 配置每台 48 核 128G12 × 4TB SSDQ20如何设计一个秒杀系统中的消息队列方案场景100 万人抢购 1000 件商品不用 MQ 的问题10 万人同时下单数据库直接被打爆超卖并发更新库存导致数据不一致用 MQ 解决的架构用户下单请求 ↓ 限流Nginx / API Gateway 限制 QPS ↓ 写入 MQ 订单队列削峰 ↓ 多个 Worker 异步处理 ├→ 库存服务原子扣减 ├→ 订单服务创建订单 └→ 通知服务发送通知 ↓ 返回用户下单成功正在处理MQ 关键设计顺序性同一商品的秒杀要保证顺序按商品ID路由到同一 Partition幂等性重复下单要能识别并拒绝Redis SETNX 防重复库存一致性用 Redis 预扣减库存 MQ 异步落库双重保障超时处理下单超时如 10 分钟未支付消息不处理库存自动释放Q21如何保证 MQ 的高可用从四个层面回答1. MQ 集群层面Broker 多副本replication.factor 3跨机房部署不同可用区ISR 机制保证数据不丢2. 生产者层面acks-1 重试机制集群部署多个 Broker一个挂了自动切换3. 消费者层面Consumer Group 多实例一个挂了其他接管手动提交 offset幂等消费4. 监控告警消息积压告警队列深度超过阈值Broker 存活告警消费延迟告警Q22如果让你用 C 从零实现一个简化版 Kafka你会怎么做这是一个综合设计题考察你对 Kafka 核心原理的理解深度。核心模块设计1. 网络层借鉴 Reactor 模式Acceptor接收连接→ 分配给 EventLoop → Channel 监听读写事件 EventLoop 使用 epoll你已经实现过2. 消息存储Topic → Partition → Log File顺序追加 → Index File稀疏索引 → Segment File按大小滚动3. 分区策略Producer 发送时 → 根据 key 哈希选择 Partition → 写入对应 Partition 的 Leader → Leader 异步同步给 Follower类 Raft 共识4. 消费模型Consumer Group → 每个 Consumer 分配若干 Partition → 维护消费进度offset → 支持重平衡Rebalance关键区别你不需要实现的部分Controller 选举可用 ZooKeeper 或简化版多副本强一致性简化版用单副本事务消息复杂面试时提一下即可一个综合回答我会分四层做。网络层用我已有的 Reactor 框架实现一个 Acceptor 接收连接多个 EventLoop 处理 I/O 事件。存储层参考 Kafka 的 Log Segment 结构按时间或大小滚动切分文件配套稀疏索引支持快速查找。分区路由层按 key 哈希决定写入哪个 PartitionLeader 接收写入后异步同步给 Follower。消费层维护 Consumer Group 和 offset支持 Rebalance。这个简化版不支持强一致性多副本如果要加可以用 Raft 协议实现 Leader 选举和日志复制etcd/Consul 就是这么做的。Part 5面试模拟自测模拟面试流程每题 3 分钟找一个同学或对着镜子按以下流程回答每道题结论先行5 秒先说核心答案分点展开2 分钟2-3 个要点每个要点一句话解释举例说明30 秒用一个具体场景或数字佐证追问预判自问自答如果面试官追问你会怎么答自测检查清单Q1-Q5 基础概念能在 1 分钟内回答清楚Q6-Q13 进阶原理能画图解释Q14-Q18 项目问题能结合自己项目回答Q19-Q22 系统设计能给出完整架构Q22 C 实现题能讲清楚设计思路面试核心技巧1. 用数字说话不要说很快说QPS 5 万p99 延迟 10ms不要说支持高并发说实测 5000 并发连接稳定运行2. 画图比说更清晰Kafka 架构图、Rebalance 流程图、存储结构图面试时在白板上画比纯语言描述更直观3. 展示主动思考说完方案后主动说不过这个方案也有缺点比如…展示你不是只会用还知道边界和 trade-off4. 关联已有项目每个知识点尽量关联到你做过的项目比如我在内存池里用过类似的思想… “我的网络框架和 Kafka 的网络层设计思路一致…”

更多文章