Kafka架构与核心概念
约 1546 字大约 5 分钟
kafkaarchitecture
2025-05-29
概述
Apache Kafka是由LinkedIn开发并开源的分布式流处理平台。它以高吞吐量、低延迟、高可用和持久化存储为核心特性,广泛应用于日志收集、消息队列、流处理、事件驱动架构等场景。本文深入解析Kafka的架构设计与核心概念。
整体架构
核心概念
Broker
Kafka集群由多个Broker组成,每个Broker是一个Kafka服务器实例,负责存储和服务数据。
Topic与Partition
Topic是消息的逻辑分类,每个Topic被划分为多个Partition。Partition是Kafka并行度和扩展性的基本单位。
Replica(副本)
每个Partition有多个副本(Replica),分布在不同的Broker上。一个Leader副本处理所有的读写请求,Follower副本从Leader同步数据。
ISR(In-Sync Replicas)
ISR是与Leader保持同步的副本集合。只有ISR中的副本才有资格被选举为新的Leader。
Producer设计
消息发送流程
Properties props = new Properties();
props.put("bootstrap.servers", "broker1:9092,broker2:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
// acks配置:控制可靠性
props.put("acks", "all"); // all/-1: 等待所有ISR副本确认
// 1: 只等Leader确认
// 0: 不等待确认
// 批量发送配置
props.put("batch.size", 16384); // 批次大小 16KB
props.put("linger.ms", 5); // 最大等待时间 5ms
props.put("compression.type", "snappy"); // 压缩算法
// 重试配置
props.put("retries", 3);
props.put("retry.backoff.ms", 100);
props.put("enable.idempotence", true); // 启用幂等性
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
// 异步发送
producer.send(new ProducerRecord<>("orders", "order-123", orderJson),
(metadata, exception) -> {
if (exception != null) {
log.error("Send failed", exception);
} else {
log.info("Sent to partition={}, offset={}",
metadata.partition(), metadata.offset());
}
});Producer内部架构
Consumer模型
消费者组
Offset管理
// 手动提交offset(推荐方式)
Properties props = new Properties();
props.put("enable.auto.commit", "false"); // 关闭自动提交
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Collections.singletonList("orders"));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
// 处理消息
processRecord(record);
}
// 同步提交(确保处理完成后再提交)
consumer.commitSync();
// 或精确提交到特定offset
// consumer.commitSync(Map.of(
// new TopicPartition("orders", 0),
// new OffsetAndMetadata(lastProcessedOffset + 1)
// ));
}日志存储结构
Kafka将消息以日志(Log)的形式存储在磁盘上,这是其高吞吐量的基础。
Topic: orders, Partition: 0
├── 00000000000000000000.log # 数据文件(第一个Segment)
├── 00000000000000000000.index # 偏移量索引
├── 00000000000000000000.timeindex # 时间戳索引
├── 00000000000053682400.log # 第二个Segment
├── 00000000000053682400.index
├── 00000000000053682400.timeindex
└── leader-epoch-checkpoint高性能秘诀
1. 顺序写入:消息追加到文件末尾,避免随机IO
- 顺序写性能接近内存写入(SSD上可达数百MB/s)
2. Page Cache:利用操作系统的页缓存
- 消息先写入Page Cache,由OS异步刷盘
- 读取时直接从Page Cache返回
3. Zero-Copy:使用sendfile()系统调用
- 数据从磁盘直接传输到网络,不经过用户空间
- 减少了两次数据拷贝和上下文切换
4. 批量处理 + 压缩
- Producer端批量发送
- Broker端以压缩的批次存储
- Consumer端批量拉取ZooKeeper依赖到KRaft
传统Kafka依赖ZooKeeper进行元数据管理、Controller选举等。从Kafka 2.8开始引入KRaft模式,用Raft协议替代ZooKeeper。
关键配置对比
| 配置项 | 说明 | 推荐值 |
|---|---|---|
replication.factor | 副本数 | 3 |
min.insync.replicas | 最小ISR数 | 2 |
acks | Producer确认级别 | all |
unclean.leader.election.enable | 是否允许非ISR副本选Leader | false |
log.retention.hours | 日志保留时间 | 168 (7天) |
num.partitions | 默认分区数 | 根据吞吐量计算 |
计算分区数:
目标吞吐量 / min(Producer单分区吞吐, Consumer单分区吞吐)
例:100MB/s 目标 / 10MB/s 单分区 = 10个分区总结
Kafka的架构设计围绕"分布式提交日志"这一核心抽象,通过分区实现水平扩展,通过副本机制保证高可用,通过顺序IO、零拷贝、批量处理实现高吞吐。理解Broker、Topic、Partition、Replica、ISR等核心概念以及Producer/Consumer的工作原理,是正确使用和调优Kafka的基础。
贡献者
更新日志
2026/3/14 13:09
查看所有更新日志
9f6c2-feat: organize wiki content and refresh site setup于