消息队列

候选人小李面试字节跳动P6岗位,简历上写着"熟悉消息队列"。

面试官问:"你们项目里用的什么MQ?"

小李说:"Kafka。"

面试官追问:"Kafka 怎么保证消息不丢失?"

小李开始背:"生产者端、Broker端、消费者端……"背完面试官又问:"那消费者端具体怎么写才能不丢消息?光开启自动提交行不行?"

小李额头开始冒汗。

这个问题,卡住了80%的候选人。

【面试官心理】

我问他MQ,其实不是在考背书。我是想知道:他在项目里到底有没有用过MQ,是被动接手的还是主动设计过的。自动提交offset这个点,没踩过坑的人根本答不上来。

一、内容版图

本模块覆盖主流消息队列的面试核心点:

目录覆盖内容
kafka-architectureKafka 整体架构、Leader/Follower 机制、日志存储
kafka-partition分区策略、分区分配、消费者组
kafka-reliability消息可靠性保障、ISR 机制、ACK 策略
kafka-orderingKafka 顺序消息、因果一致性
kafka-message-loss消息丢失场景与排查
rocketmq-architectureRocketMQ 架构、NameServer、Broker 角色
rocketmq-transaction事务消息原理、半消息、回查机制
rocketmq-orderingRocketMQ 顺序消息实现
comparison三种 MQ 横向对比:Kafka vs RocketMQ vs RabbitMQ
selection选型指南:什么场景用什么 MQ
scenariosMQ 在项目中的典型使用场景
backlog消息堆积、积压处理方案

二、高频面试题地图

2.1 选型对比 🔴

第一层:三种 MQ 的特点
  → Kafka:高性能、高吞吐,适合大数据场景
  → RocketMQ:事务消息、顺序消息,适合电商/交易场景
  → RabbitMQ:灵活路由、Erlang 实现,适合中小型系统

第二层:为什么你们选 Kafka 而不是 RocketMQ?
  → 团队技术栈、数据量级、延迟要求

第三层:Kafka 的 PageCache 是什么?
  → 磁盘顺序读写、零拷贝、mmap 机制
💡

面试官问选型,其实是在看你有没有"技术选型"的意识。能说出技术方案的取舍,比单纯背特性强十倍。

2.2 消息可靠性 🔴

第一层:怎么保证消息不丢失?
  → 生产者端:ACK 策略(0/1/all)
  → Broker 端:副本机制、ISR 集合
  → 消费者端:手动提交 offset

第二层:ACK=all 就一定不丢消息吗?
  → ISR 为空时会退化成 ACK=1
  → min.insync.replicas 参数的作用

第三层:消费者端丢消息的场景
  → 自动提交 offset + 手动处理业务 = 丢消息
  → 正确姿势:手动提交 + 业务成功后再提交
⚠️

90%的候选人只知道"开启手动提交",但说不清楚"先提交还是先处理业务"这个顺序问题。这个才是真正丢消息的场景。

【面试官心理】

我问他消息可靠性,其实是在试探他有没有在生产环境踩过坑。只会配置不知道原理的,只能答到第二层。

2.3 顺序消息 🟡

第一层:Kafka 怎么保证顺序?
  → 单分区顺序:同一个 Partition 内的消息有序
  → 消费者端:单线程消费

第二层:全局顺序 vs 分区顺序
  → Kafka 只能保证分区内的顺序
  → 要全局顺序需要单分区 or 使用 RocketMQ

第三层:因果一致性
  → 跨分区的消息因果关系怎么处理?

2.4 消息积压 🟡

第一层:消息积压了怎么办?
  → 消费者挂了吗?网络问题?
  → 扩容消费者、降低消费复杂度

第二层:怎么避免消息积压?
  → 监控告警、限流、背压机制

第三层:MQ 延迟/TTL 机制
  → 消息过期了怎么处理?
  → 死信队列(Dead Letter Queue)

2.5 幂等性 🟡

第一层:消费者端怎么保证幂等?
  → 唯一键、乐观锁、分布式锁
  → 数据库唯一索引、Redis 去重

第二层:MQ 本身支持幂等吗?
  → Kafka:没原生幂等,靠业务方
  → RocketMQ:支持消息幂等(msgId)

2.6 事务消息 🟢

第一层:RocketMQ 事务消息的原理
  → 半消息(Half Message)、本地事务、回查
  → 事务状态:COMMIT/ROLLBACK/UNKNOWN

第二层:和普通消息有什么区别?
  → 事务消息多了一个"确认"环节
  → 性能比普通消息差多少?

第三层:你们用过事务消息吗?
  → 典型场景:下单扣库存
  → 怎么避免本地事务成功但消息发送失败?

【面试官心理】

事务消息是给P7准备的加分项。答不出来不扣分,但能说清楚原理和适用场景的,基本都能过P7面试。

三、生产避坑指南

3.1 Kafka 常见翻车点

场景问题后果解决方案
消费者组 rebalance分区分配抖动消息处理延迟调整 session.timeout.ms
PageCache 刷盘机器内存不足性能急剧下降合理配置内存、关闭 Swap
分区数不合理分区过多导致文件句柄耗尽Broker 宕机按数据量估算分区数
消费者 offset 提交自动提交+业务失败消息丢失手动提交+业务成功后提交

3.2 消息堆积处理流程

1. 先看消费者是否正常
   → jstack 查看线程堆栈
   
2. 看消费速度 vs 生产速度
   → kafka-consumer-groups --describe

3. 紧急处理:扩容消费者
   → 临时机器启动新消费者实例

4. 后续优化:提高消费并发度
   → 批量消费、异步处理

3.3 消息丢失排查

// 典型丢消息场景:自动提交 + 业务异常
while (true) {
    ConsumerRecord<String, String> record = consumer.poll();
    try {
        process(record);
        // 错误:业务处理完才提交,但自动提交已经配置了
        // 正确做法:手动提交 offset
    } catch (Exception e) {
        log.error("处理失败", e);
    }
}
📖 点击展开:Kafka 可靠性配置清单
# 生产者端
acks=all              # 等待所有副本确认
retries=3            # 重试次数
enable.idempotence=true  # 开启幂等性

# Broker端
min.insync.replicas=2    # ISR 最少副本数
unclean.leader.election.enable=false  # 禁止脏leader选举

# 消费者端
enable.auto.commit=false  # 手动提交
auto.offset.reset=earliest  # 从最早位置消费

四、学习路径指引

4.1 P5 层级:会用 MQ

  • 知道 Kafka/RocketMQ/RabbitMQ 的基本特性和区别
  • 能说清楚消息的发送和消费流程
  • 会配置消费者组、topic、分区

期望回答:能讲清楚 Kafka 的基本架构和消息发送流程。

4.2 P6 层级:懂原理

  • 能说清楚 ACK 策略、ISR 机制、消费者 offset 提交
  • 知道顺序消息的原理和限制
  • 有生产环境排查消息丢失/积压的经验

期望回答:能回答追问,不怵细节,有实战案例。

4.3 P7 层级:能选型、能架构

  • 能根据业务场景做技术选型
  • 知道事务消息的原理和适用场景
  • 有 MQ 相关生产故障的排查和解决经验
  • 了解 MQ 延迟、吞吐量、可靠性的权衡

期望回答:有全局视野,能说清楚取舍,能讲清楚一个完整的生产问题排查过程。

五、导航指引

💡

MQ 面试的进阶路径:先搞懂"消息不丢失"这个核心问题,再准备"顺序消息"和"积压处理"的生产案例,最后能说清楚三种 MQ 的取舍。做到这三点,P6 面试稳了。