Kafka FAQ
内容:基础、原理、生产、消费、存储、分区、副本、事务、调优、运维、故障等。
Kafka 快的原因主要有 5 点:
-
顺序写磁盘(Sequential Write)
Kafka 的 log segment 是追加写,磁盘顺序写比随机写快几个数量级。
-
零拷贝(Zero Copy)
使用 sendfile(),数据直接从 Page Cache -> NIC,减少用户态/内核态拷贝。
-
Page Cache 强依赖
Kafka 不自己缓存数据,直接利用 Linux PageCache,提高读写性能。
-
批量处理(Batch & Compression)
Producer 批量写(batch.size + linger.ms),Broker 端消息压缩。
-
分区并行(Partition Parallel)
Topic 多分区并行读写,吞吐线性提升。
- Topic:消息的逻辑分类。
- Partition:存储和并行度的最小单位。分区越多,吞吐越高。
- Replica:副本,用于容灾与高可用。
设计分区是因为:
- 提升吞吐(并行写入/读取)
- 支持集群水平扩展
- HA 依赖副本机制
ISR 全称 In-Sync Replica(同步副本集合)
- 只有同步进度足够快的 Follower 才能进入 ISR
- Leader 挂掉时 只能从 ISR 中选新的 Leader
- 配合 min.insync.replicas + acks=all 保证数据不丢
ISR 是 Kafka 保证高可靠性(高一致性)的关键。
- LEO(Log End Offset):每个副本自己的写入进度。
- HW(High Watermark):所有 ISR 副本都同步到的数据偏移量,消费者只能读到 HW 以内的数据。
- LSO:用于事务的逻辑点(很少问)
重点:
消费者只能消费到 HW 以内的消息,不会看到未同步完成的数据。
开启幂等性:
enable.idempotence=true
开启最强写入策略:
acks=all
retries=∞
设置:
min.insync.replicas >= 2
replication.factor >= 3
- 关闭自动提交 offset
- 手动在业务完成后提交 offset
Producer 使用幂等性 + 事务:
enable.idempotence=true
transactional.id=xxx
Consumer 使用 幂等消费逻辑(如通过主键唯一约束)
给出一句金句:
Kafka 保证不丢,但不保证不重复。需要业务端实现幂等消费。
包括 3 部分:
- 幂等性 Producer
- 事务性 Producer(两阶段提交)
- 事务性消费(commit offset 写入同一个事务)
这是 Kafka Streams 和 Flink 最经典的场景。
Rebalance = 消费者组内部消费者变化时,重新分配分区。
发生在:
- 新 consumer 加入
- consumer 退出
- consumer 崩溃被检测到(心跳超时)
- 分区数量变更(alter partitions)
- group coordinator 切换
影响:消费会暂停,吞吐下降
优化手段:
- session.timeout.ms 调大
- max.poll.interval.ms 配置合理
- 使用 Cooperative Rebalance(Kafka 2.4+)
- 避免频繁重启 consumer
绝不是。
缺点:
- 更多文件句柄
- 更多网络连接
- Leader 选举开销更大
- 延迟上升
- Controller 负载更高
- rebalance 更慢
最佳分区数经验:
分区 = 生产吞吐 / 单分区最大吞吐
业务峰值 QPS 大,可以多用一些分区。
通过 sendfile() 系统调用实现:
用户态 -> 内核态 -> 用户态 -> NIC
减少为:
PageCache -> NIC
不经过用户态,减少拷贝次数,提高吞吐。
Zookeeper 模式:
- Controller 监听 broker 上线/下线事件
- 发现 Leader 宕机
- Controller 从 ISR 中选择新 Leader
- 更新元数据到 ZK
- 通知所有 Broker
KRaft 模式:
- 使用 Raft 协议选举
- 不依赖 Zookeeper
拉模式(Pull)
原因:
- Consumer 自行决定消费速度
- 减少 Broker 压力
- 可批量拉取,提高吞吐
Kafka 依赖 OS Page Cache 提升:
- 写性能(顺序写->Page Cache)
- 读性能(热数据在 Cache)
Kafka 不做用户态缓存,完全把缓存交给 Linux。
靠两个机制:
-
ISR + min.insync.replicas
只有 ISR 能选为 leader
-
unclean.leader.election
unclean.leader.election.enable=false
避免从不同步的 Follower 中选 Leader 导致数据丢失。
处理策略:
- 增加 Consumer 实例
- 增加 Topic 分区
- 提升 Consumer poll 批量数
- 使用多线程处理消息
- Producer 降压(控制写入速度)
关键命令:
kafka-consumer-groups.sh --describe --group xxx
log.cleanup.policy = compact
保留每个 key 的最新 value。
适用于:
- 账号状态
- 配置同步
- 去重场景
靠 Producer ID(PID)+ sequence number(序号)
Broker 检查是否重复:
- 如果 seq 与上次相同 -> 丢弃
- 如果更大 -> 正常写入
扩 Broker 后:
- 分区不会自动迁移
- 需要 reassign partitions 手动均衡
这是运维常见陷阱。
两阶段提交:
- Prepare(写事务日志)
- Commit(提交 Write + Offset)
适用于:
- Exactly Once
- Kafka Streams
- Flink Connector
| 维度 | Kafka | RabbitMQ |
|---|---|---|
| 模型 | 日志系统 | 消息队列 |
| 吞吐 | 高(百万级) | 中低 |
| 顺序性 | 分区内有序 | 队列内有序 |
| 延迟 | 稍高 | 低 |
| 使用场景 | 大数据、日志、链路跟踪 | 业务消息、任务队列 |
Kafka 是分布式日志系统,RabbitMQ 是用于业务解耦的 MQ。