Kafka 核心原理?

2025年 阅读约 15 分钟 面试指南 · 消息中间件

深入解析Kafka核心原理:分区机制(Partition)、副本机制(Replica)、ISR(In-Sync Replicas)、HW/LEO水位线、Controller选举、零拷贝(sendfile)、日志分段(LogSegment),附面试模拟问答。

一句话总结

Kafka 核心设计:分区(Partition,并行+扩展的基础)、副本(Replica,高可用的基础)、ISR(In-Sync Replicas,与 Leader 保持同步的副本集合)。关键概念:HW(High Watermark,消费者可见的最高 offset)、LEO(Log End Offset,日志末尾 offset)。高性能秘诀:顺序写磁盘(日志追加)、零拷贝(sendfile 系统调用,数据不经过用户态)、Page Cache(利用操作系统缓存)、批量压缩

初级理解

Kafka 架构

# Kafka 核心组件 # Broker:Kafka 服务器节点 # Topic:消息主题(逻辑概念) # Partition:分区(物理概念,Topic 的子集) # Replica:副本(分区的备份) # Producer:生产者 # Consumer:消费者 # Consumer Group:消费者组 # Zookeeper/KRaft:元数据管理(Controller 选举) # 分区的作用 # 1. 并行处理:多个分区可并行读写 # 2. 水平扩展:分区分布在不同 Broker 上 # 3. 提高吞吐:分区越多,并行度越高 # 副本的作用 # 1. 高可用:Leader 宕机,Follower 提升为 Leader # 2. 数据冗余:每个分区有多个副本

中级深入

ISR 机制

# ISR(In-Sync Replicas):与 Leader 保持同步的副本集合 # Leader 在 ISR 中,所有 ISR 副本都同步了消息 # 副本加入 ISR 条件 # Follower 与 Leader 的 LEO 差距 < replica.lag.time.max.ms(默认 30s) # 副本踢出 ISR 条件 # Follower 超过 30s 未同步 → 踢出 ISR # ISR 的作用 # 1. 保证消息不丢失 # acks=all → 所有 ISR 副本确认后才返回成功 # 2. 保证数据一致性 # Leader 选举时,只从 ISR 中选新 Leader # 最小 ISR 数 # min.insync.replicas = 2 # 至少 2 个 ISR 副本确认,消息才算成功 # 如果 ISR 数量不足,生产者写入失败

HW 和 LEO

# LEO(Log End Offset):日志末尾偏移量 # 下一条消息将被写入的位置 # HW(High Watermark):高水位 # 消费者只能消费 HW 之前的消息 # HW = min(所有 ISR 副本的 LEO) # 保证消费者不会读到可能丢失的消息 # 示例 # Leader LEO=100, Follower1 LEO=95, Follower2 LEO=90 # HW = min(100, 95, 90) = 90 # 消费者只能消费 offset < 90 的消息 # HW 的作用 # 1. 保证消费数据一致性 # 2. Leader 切换时,新 Leader 从 HW 开始 # 3. 防止消费者读到未提交的消息

高级拓展

零拷贝(Zero Copy)

# 传统 IO(4 次拷贝,2 次 CPU 拷贝 + 2 次 DMA 拷贝) # 磁盘 → 内核缓冲区 → 用户缓冲区 → Socket 缓冲区 → 网卡 # 零拷贝(sendfile,2 次拷贝,0 次 CPU 拷贝 + 2 次 DMA 拷贝) # 磁盘 → 内核缓冲区 → 网卡(DMA 直接传输) # 数据不经过用户态,CPU 不参与拷贝 # Kafka 使用零拷贝 # 1. 生产者写入:数据写入 Page Cache(内核缓冲区) # 2. 消费者读取:sendfile 直接从 Page Cache 发送到网卡 # 3. 数据不经过 Kafka 进程的用户空间 # 性能提升 # 传统 IO:CPU 拷贝 2 次,上下文切换 4 次 # 零拷贝:CPU 拷贝 0 次,上下文切换 2 次 # 吞吐量提升 2-3 倍

Controller 选举

# Controller:Kafka 集群的管理者 # 职责: # 1. 分区 Leader 选举 # 2. ISR 管理 # 3. Broker 上下线处理 # 4. 分区重分配 # Controller 选举(基于 Zookeeper) # 1. 所有 Broker 竞争创建 /controller 临时节点 # 2. 创建成功的成为 Controller # 3. Controller 宕机 → 临时节点删除 → 重新选举 # KRaft 模式(Kafka 3.x+,去 Zookeeper) # 使用 Raft 协议选举 Controller # 元数据存储在 Kafka 内部 Topic(__cluster_metadata)

实战场景

场景:Kafka 分区数规划

# 分区数规划原则 # 1. 分区数 ≥ 消费者数(一个分区只能被一个消费者消费) # 2. 分区数不是越多越好 # - 分区越多,文件句柄越多 # - 分区越多,Leader 选举越慢 # - 分区越多,内存占用越大 # 3. 经验值 # - 低吞吐:3-6 个分区 # - 中吞吐:6-12 个分区 # - 高吞吐:12-30 个分区 # 分区数计算公式 # 分区数 = max(目标吞吐量 / 单分区吞吐量, 消费者数) # 单分区吞吐量:约 10-20 MB/s # 示例 # 目标吞吐量:100 MB/s # 单分区吞吐量:10 MB/s # 消费者数:8 # 分区数 = max(100/10, 8) = 10

面试模拟

面试官:Kafka 为什么这么快?

你:四大原因:顺序写磁盘(日志追加,接近磁盘顺序写极限)、零拷贝(sendfile,数据不经过用户态)、Page Cache(利用操作系统缓存)、批量压缩(减少网络传输)。

面试官:ISR 是什么?有什么作用?

你:ISR 是与 Leader 保持同步的副本集合。作用:保证消息不丢失(acks=all 时所有 ISR 确认)、保证数据一致性(Leader 选举只从 ISR 中选)、通过 HW 保证消费者读到一致的数据。