← 返回分布式系统
🚀 Kafka 深入 · 面试高频

Kafka 深入剖析

从 Topic / Partition / Replica / ISR / HW 到零拷贝,把 Kafka 为什么能"高吞吐、高可靠、顺序、不丢"讲透。面试官最爱追问的细节都在这里。

🗂️核心模型

Kafka 的"高吞吐"来自一个朴素设计:日志就是数组,追加即可,绝不随机改。

Topic:order-events Partition-0 Partition-1 Partition-2 每个 Partition 是一个有序、不可变的日志(append-only) 消息按 offset 递增编号;多 partition 实现并行与横向扩展
关键概念:Producer 按 key 哈希到 partition;Consumer Group 中每个 consumer 分配若干 partition;partition 数 = 最大并行消费度。

🔢Partition 与顺序保证

顺序的边界

Kafka 只保证单个 partition 内消息有序。跨 partition 不保序。

因此:要"同一订单顺序"(如创建→支付→发货),就把订单ID 作为 key,使其哈希到固定 partition,单线程消费该 partition 即可。

⚖️
权衡:partition 越多 → 并行度越高、吞吐越大,但顺序粒度越粗(只能保证"同 key 顺序")。不要为了全局顺序而无脑用单 partition——那是反模式。

🪞副本机制与 ISR

每个 Partition 有多个副本(Replica),分布在不同 broker 上。其中一个是 Leader,其余是 Follower。

Broker-0 P0-Leader P1-Follower P2-Follower Broker-1 P0-Follower P1-Leader P2-Follower Broker-2 P0-Follower P1-Follower P2-Leader 每个 partition 的 Leader 负责读写,Follower 向 Leader 拉取同步
ISR(In-Sync Replicas,同步副本集合):与 Leader 保持"同步"的副本(落后不超过 replica.lag.time.max.ms)。只有 ISR 中的副本才有资格被选举为新 Leader。
🧠
为什么有 ISR:避免"一个远远落后的 Follower 被提升为 Leader 后丢数据"。只有 ISR 成员能当 Leader,保证新 Leader 拥有全部已提交数据。

📏HW 与 LEO

这两个水位线决定了"消费者能读到哪、数据是否算提交",是 Kafka 不丢不重的核心。

概念全称含义
LEOLog End Offset每个副本日志的下一条写入位置(即当前最大 offset+1)
HWHigh WatermarkISR 中最小的 LEO,即"所有 ISR 都有的最后一条"——消费者只能读到 HW 之前
为什么用 HW:一条消息要被所有 ISR 副本都写入后,才对消费者"可见"(即推进 HW)。这样哪怕 Leader 宕机,新 Leader 也一定含有 HW 之前的数据,不会读到未提交/会丢失的消息。
⚠️
经典坑:若按 LEO 对消费者可见,Leader 宕机后新 Leader 没这条 → 消息"消失"(幻读)。HW 机制正是为堵这个洞。0.11 后引入 Leader Epoch 进一步消除 HW 带来的边界问题。

🔄生产 / 消费流程

Producer 发送:按 key 选 partition(默认轮询或哈希),消息先攒在 batch,后台线程发送。
Leader 写入:Leader 把消息追加到本地 log,并更新 LEO。
Follower 同步:Follower 拉取 Leader 日志,写入本地,更新各自 LEO。
推进 HW:Leader 取 ISR 中最小 LEO 作为新 HW,消息对消费者可见。
Consumer 拉取:Consumer 按位移(offset)从 partition 拉取,处理完提交位移,下次从新位移继续。
✅
acks 配置:acks=0(不等确认,快但可能丢);acks=1(Leader 写入即确认,Leader 宕机可能丢);acks=all(ISR 全写才确认,最可靠)。可靠性要求高用 all。

⚡零拷贝(Zero-Copy):吞吐之本

Kafka 消费时要把磁盘日志发给网络,传统路径要经过"内核→用户→内核"多次拷贝。Kafka 用 sendfile 系统调用跳过用户态。

传统 I/O:磁盘 → 内核页缓存 → 用户缓冲区 → socket 缓冲区 → 网卡(4 次拷贝 + 2 次上下文切换)。
零拷贝 sendfile:磁盘 → 内核页缓存 → 网卡(2 次拷贝,DMA 直达,CPU 几乎不参与)。
🚀
为什么 Kafka 能扛百万/s:顺序磁盘写(磁盘顺序写比内存随机写还快)+ 零拷贝读 + 批处理(batch)+ 页缓存。四个武器叠加,吞吐远超传统 MQ。

🎯面试要点速记

模型:Topic 分多个 Partition,每个 Partition 是有序 append-only 日志,按 offset 编号。
顺序:仅 partition 内有序;同 key 哈希到同 partition 实现业务顺序。
副本:Leader 读写,Follower 拉同步;ISR=同步副本集合,仅 ISR 可当选 Leader。
HW/LEO:LEO=各副本末端;HW=ISR 最小 LEO,消费者只可见 HW 之前,防丢数据。
acks:0/1/all 三档,all 最可靠;配合 retries 防网络抖动丢消息。
零拷贝:sendfile 减少拷贝与上下文切换;+ 顺序写 + 批处理 = 高吞吐。
🔥
必考题:"Kafka 怎么保证不丢消息?"——生产端 acks=all+重试、服务端 多副本(ISR)+刷盘、消费端 先处理后提交 offset。再追问"顺序/高吞吐"就接 partition 与零拷贝。