1. Kafka 中零拷贝(Zero-Copy)是如何实现的?有什么好处?
实现方式:
Kafka 使用 Java NIO 的 FileChannel.transferTo() 方法,底层调用 Linux 的 sendfile 系统调用。
传统流程 vs 零拷贝:
- 传统流程 :磁盘 → 内核缓冲区 → 用户缓冲区 → Socket 缓冲区 → 网卡
(4 次拷贝,2 次上下文切换) - 零拷贝 :磁盘 → 内核缓冲区 → 网卡
(2 次拷贝,0 次 CPU 拷贝)
好处:
减少 CPU 拷贝和上下文切换,大幅提升磁盘到网络的数据传输性能,是 Kafka 高吞吐的关键之一。
2. Kafka 生产者发送消息时,acks 参数有哪几种取值?分别生产环境怎么选?
| 取值 | 说明 | 优缺点 | 生产建议 |
|---|---|---|---|
acks=0 |
生产者不等确认,直接发下一条 | 最快,但可能丢数据(如网络抖动) | 极少用 |
acks=1 |
Leader 写入本地日志后确认,不等待 Follower | 默认值,折中方案,但仍可能丢数据(Leader 确认后宕机) | 日志采集等对丢失不敏感的场景 |
acks=all / -1 |
Leader 等待 ISR 中所有副本写入成功 | 最可靠,不丢数据,但影响延迟 | 核心交易场景 |
3. 什么是 ISR?为什么需要它?
ISR(In-Sync Replicas) :与 Leader 保持同步的副本集合。
同步条件:副本在过去 replica.lag.time.max.ms 内未明显落后。
为什么需要 ISR?
- Leader 宕机时,只在 ISR 中选举新 Leader,保证数据不丢失。
- 相比等待全部副本同步,ISR 机制允许部分副本暂时落后而不阻塞写入,平衡了可靠性与可用性。
4. Kafka 如何保证消息不丢失?从生产者、Broker、消费者三个角度说明。
| 角色 | 措施 |
|---|---|
| 生产者 | acks=all,等待 ISR 中所有副本写入成功;设置 retries > 0;开启 enable.idempotence=true(幂等性) |
| Broker | 设置 ISR 最小副本数;unclean.leader.election.enable=false(禁止从非 ISR 选举 Leader) |
| 消费者 | 先处理业务逻辑,再手动提交 Offset(enable.auto.commit=false) |
5. Kafka 中的幂等生产者(Idempotent Producer)是如何实现的?
- 开启方式 :
enable.idempotence=true - 实现原理 :
- 每个生产者分配一个 Producer ID(PID)
- 每条消息带序列号,Broker 按分区维护 PID 和序列号
- 发现重复序列号则拒绝写入
- 作用:避免网络重试导致的消息重复(单分区、单会话内),是实现 Exactly-Once 语义的第一步。
6. 什么是 Rebalance?什么时候发生?它对消费性能有什么影响?
Rebalance:消费者组内重新分配分区的协调机制。
触发时机:
- 消费者组内有成员加入或退出(含心跳超时、超时未消费被踢)
- 订阅的 Topic 分区数增加
对性能的影响:
- 旧版(急切重平衡):所有消费者停止消费,重新分配,易造成消息积压
- 新版(增量重平衡):尽量保留原有分区,只调整变动部分,影响更小
7. Kafka 为什么要采用 Pull 模式?有什么缺点?
| 优点 | 缺点 |
|---|---|
| 消费者按自身能力拉取,不易被推死 | 无数据时空轮询(可配置 fetch.wait.max.ms 缓解) |
支持批量拉取(max.poll.records) |
需手动处理 Offset 提交,复杂度略高 |
| 慢消费者不阻塞其他消费者 |
8. 如何避免 Kafka 消息重复消费?如果重复消费已经发生,怎么解决?
避免重复消费:
- 消费端幂等处理(数据库唯一键、Redis 原子操作、业务状态机)
- 处理完业务再提交 Offset(At-Least-Once + 幂等 = Exactly-Once)
已发生重复消费如何解决:
- 利用消息唯一 ID(如 UUID)去重表,消费前查询是否已处理
- 数据库场景使用
insert on duplicate key update
9. Kafka 中 Leader 和 Follower 的同步机制是怎样的?如果 Follower 落后太多会发生什么?
同步机制:
Follower 从 Leader 拉取数据并写入日志,主动发送 Fetch 请求。
Follower 落后太多:
- 超过
replica.lag.time.max.ms(默认 30s)则被踢出 ISR - 被踢出的 Follower 继续追赶,追平后重新加入 ISR
- 若所有 ISR 副本都宕机,且禁止从非 ISR 选举(
unclean.leader.election.enable=false),则分区不可用
10. 说说 Kafka 中 auto.offset.reset 参数的作用及常用取值。
作用:
当消费者没有初始 Offset 或当前 Offset 已失效(如数据被删除)时,决定从何处开始消费。
| 取值 | 行为 | 生产建议 |
|---|---|---|
earliest |
从最早的消息开始 | 首次启动且依赖全部历史数据 |
latest(默认) |
从最新消息开始 | 仅关心新数据 |
none |
没有 Offset 时抛异常 | 调试或严格场景 |