Kafka核心原理(一):概述与架构设计
2020-04-06·5 分钟阅读
Kafka核心原理(一):概述与架构设计
前言
Apache Kafka 是当今最流行的分布式流处理平台之一,每天处理着数万亿条消息。从 LinkedIn 内部项目到 Apache 顶级项目,Kafka 已经成为现代数据架构的核心组件。本系列将从零开始,深入剖析 Kafka 的核心原理,帮助你理解其设计哲学和实现细节。
技术亮点概览
Kafka 核心原理系列涵盖分布式消息系统的关键技术点:
核心技术亮点
| 技术点 | 难度 | 面试价值 | 实现章节 |
|---|---|---|---|
| 零拷贝与顺序写 | ⭐⭐⭐⭐ | 高性能IO理解 | 第7章 |
| 分区副本机制 | ⭐⭐⭐⭐ | 分布式一致性 | 第5章 |
| Consumer Group Rebalance | ⭐⭐⭐⭐ | 分布式协调 | 第4章 |
| Exactly Once语义 | ⭐⭐⭐⭐⭐ | 消息可靠性 | 第6章 |
| ISR同步机制 | ⭐⭐⭐⭐ | 高可用设计 | 第5章 |
| KRaft共识协议 | ⭐⭐⭐⭐⭐ | 分布式共识 | 第8章 |
| 消息压缩与批量处理 | ⭐⭐⭐ | 性能优化 | 第7章 |
面试常见问题覆盖
通过本系列文章,你将能够回答以下面试高频问题:
-
架构设计
- Kafka 为什么这么快?零拷贝原理是什么?
- Kafka 如何保证消息不丢失?
- Kafka 如何保证消息顺序?
-
分布式机制
- Kafka 的副本机制是如何工作的?
- Leader 选举过程是怎样的?ISR 是什么?
- Consumer Group Rebalance 的触发条件和过程?
-
可靠性保证
- Kafka 如何实现 Exactly Once 语义?
- ACK 机制的三种级别有什么区别?
- 幂等性生产者是如何实现的?
Kafka 是什么?
定义与定位
Apache Kafka 是一个分布式流处理平台,最初由 LinkedIn 开发,后来贡献给 Apache 成为顶级项目。Kafka 的核心特性:
- 高吞吐量:单节点可达百万级 TPS
- 低延迟:端到端延迟可低至毫秒级
- 高可用:支持多副本、自动故障转移
- 持久化:消息持久化到磁盘,支持回溯
- 水平扩展:支持在线扩容,线性扩展能力
与传统消息队列对比
| 特性 | Kafka | RabbitMQ | ActiveMQ |
|---|---|---|---|
| 吞吐量 | 百万级 TPS | 万级 TPS | 万级 TPS |
| 延迟 | 毫秒级 | 微秒级 | 毫秒级 |
| 持久化 | 磁盘顺序写 | 内存+磁盘 | 内存+磁盘 |
| 消息模型 | 发布-订阅 | 多种模型 | 多种模型 |
| 消息顺序 | 分区内有序 | 队列有序 | 队列有序 |
| 回溯消费 | 支持 | 不支持 | 不支持 |
| 适用场景 | 日志、流处理 | 业务消息 | 业务消息 |
核心应用场景
┌─────────────────────────────────────────────────────────────────┐
│ Kafka 应用场景全景 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 消息系统 2. 日志收集 3. 流处理 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 服务解耦 │ │ 日志聚合 │ │ 实时计算 │ │
│ │ 异步处理 │ │ 集中存储 │ │ ETL管道 │ │
│ │ 流量削峰 │ │ 日志分析 │ │ CEP处理 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ 4. 事件溯源 5. 用户活动追踪 6. IoT数据管道 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 事件存储 │ │ 点击流 │ │ 传感器数据 │ │
│ │ 状态重建 │ │ 用户行为 │ │ 设备监控 │ │
│ │ 审计日志 │ │ 推荐系统 │ │ 实时告警 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
核心概念
消息模型
Kafka 采用发布-订阅模式,核心概念包括:
┌─────────────────────────────────────────────────────────────────┐
│ Kafka 消息模型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Producer Topic Consumer │
│ │ │ │ │
│ │ ┌──────────────────┼──────────────────┐ │ │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Partition 0│ │ Partition 1│ │ Partition 2│ │
│ │ ┌──────┐ │ │ ┌──────┐ │ │ ┌──────┐ │ │
│ │ │Msg-1 │ │ │ │Msg-1 │ │ │ │Msg-1 │ │ │
│ │ │Msg-2 │ │ │ │Msg-2 │ │ │ │Msg-2 │ │ │
│ │ │Msg-3 │ │ │ │Msg-3 │ │ │ │Msg-3 │ │ │
│ │ └──────┘ │ │ └──────┘ │ │ └──────┘ │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
核心组件详解
1. Producer(生产者)
负责将消息发布到 Kafka 集群:
// 生产者核心配置
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("acks", "all"); // 确认级别
props.put("retries", 3); // 重试次数
props.put("batch.size", 16384); // 批量大小
props.put("linger.ms", 5); // 等待时间
props.put("buffer.memory", 33554432); // 缓冲区大小
props.put("compression.type", "lz4"); // 压缩类型
Producer<String, String> producer = new KafkaProducer<>(props);
2. Broker(代理服务器)
Kafka 集群中的服务节点,负责:
- 消息存储与管理
- 分区副本管理
- 消费者组协调
- 元数据管理
Kafka Broker 核心职责:
├── 消息存储
│ ├── 日志段管理(LogSegment)
│ ├── 索引文件维护
│ └── 过期消息清理
├── 副本管理
│ ├── Leader/Follower 角色管理
│ ├── ISR 维护
│ └── 日志同步
├── 请求处理
│ ├── 网络层(SocketServer)
│ ├── 请求队列
│ └── 处理线程池
└── 协调服务
├── Group Coordinator
└── Transaction Coordinator
3. Consumer(消费者)
从 Kafka 拉取消息进行处理:
// 消费者核心配置
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "my-group");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("auto.offset.reset", "earliest");
props.put("enable.auto.commit", "false");
props.put("max.poll.records", 500);
props.put("session.timeout.ms", 10000);
props.put("heartbeat.interval.ms", 3000);
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("my-topic"));
4. Topic(主题)
消息的逻辑分类,生产者发送消息到特定主题,消费者订阅主题消费消息:
Topic 设计最佳实践:
├── 命名规范
│ ├── 使用有意义的名称
│ ├── 建议格式:<领域>.<实体>.<事件>
│ └── 示例:order.payment.created
├── 分区策略
│ ├── 根据吞吐量确定分区数
│ ├── 考虑消费者并行度
│ └── 预留扩展空间
└── 保留策略
├── 基于时间:7天(默认)
├── 基于大小:-1(无限制)
└── 压缩策略:日志压缩
5. Partition(分区)
Topic 的物理分片,是实现高吞吐量的关键:
┌─────────────────────────────────────────────────────────────────┐
│ 分区的作用 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 并行处理 │
│ ├── 多个分区可以分布在不同 Broker 上 │
│ ├── 多个消费者可以并行消费不同分区 │
│ └── 提高整体吞吐量 │
│ │
│ 2. 数据分布 │
│ ├── 相同 Key 的消息始终发送到同一分区 │
│ ├── 保证分区内消息顺序性 │
│ └── 支持自定义分区策略 │
│ │
│ 3. 容错能力 │
│ ├── 每个分区可以有多个副本 │
│ ├── Leader 故障时 Follower 可以接管 │
│ └── 提供数据冗余 │
│ │
└─────────────────────────────────────────────────────────────────┘
6. Offset(位移)
消息在分区中的唯一标识:
Offset 特性:
├── 单调递增:每个分区内的 Offset 从 0 开始递增
├── 持久化:由消费者组提交到 __consumer_offsets 主题
├── 可回溯:消费者可以重置 Offset 重新消费
└── 提交策略:
├── 自动提交(可能丢失消息)
├── 同步提交(可靠但阻塞)
└── 异步提交(高性能但可能重复)
整体架构
架构图
┌─────────────────────────────────────────────────────────────────────────┐
│ Kafka 集群架构 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ ZooKeeper / KRaft │ │
│ │ (元数据管理、Controller选举、集群协调) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────┼─────────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Broker 1 │ │ Broker 2 │ │ Broker 3 │ │
│ │ (Leader) │◄─────────►│ (Follower) │◄─────────►│ (Follower) │ │
│ │ │ │ │ │ │ │
│ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │
│ │ │Topic-A │ │ │ │Topic-A │ │ │ │Topic-B │ │ │
│ │ │Part-0 │ │ │ │Part-1 │ │ │ │Part-0 │ │ │
│ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │
│ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │
│ │ │Topic-B │ │ │ │Topic-C │ │ │ │Topic-C │ │ │
│ │ │Part-1 │ │ │ │Part-0 │ │ │ │Part-1 │ │ │
│ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ▲ ▲ ▲ │
│ │ │ │ │
│ ┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐ │
│ │ Producer │ │ Producer │ │ Producer │ │
│ │ Group A │ │ Group B │ │ Group C │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Consumer Group │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │Consumer 1│ │Consumer 2│ │Consumer 3│ │Consumer 4│ │ │
│ │ │ (P0, P1) │ │ (P2, P3) │ │ (P4, P5) │ │ (P6, P7) │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
核心流程
消息生产流程
Producer 发送消息流程:
┌─────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Producer│───►│Serializer │───►│ Partitioner │───►│ RecordAccu- │
│ Client │ │ 序列化器 │ │ 分区器 │ │ mulator │
└─────────┘ └─────────────┘ └─────────────┘ │ 消息累加器 │
└──────┬──────┘
│
┌──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ RecordAccumulator │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Topic-Partitions Batches │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │Batch(T0) │ │Batch(T1) │ │Batch(T2) │ │Batch(T3) │ │ │
│ │ │ [msgs] │ │ [msgs] │ │ [msgs] │ │ [msgs] │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────┐
│ Sender Thread │
│ 发送线程 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Network Client │
│ 网络客户端 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Broker │
│ (Leader) │
└─────────────────┘
消息消费流程
Consumer 消费消息流程:
┌─────────────────────────────────────────────────────────────────────┐
│ Consumer Poll │
│ │
│ 1. 发送 FetchRequest │
│ ┌──────────┐ ┌──────────┐ │
│ │Consumer │ ──FetchRequest───► │ Broker │ │
│ │ │ ◄──FetchResponse─ │ (Leader) │ │
│ └──────────┘ └──────────┘ │
│ │
│ 2. 消息处理 │
│ ┌──────────────────────────────────────────────┐ │
│ │ Consumer Records │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │Record 1│ │Record 2│ │Record 3│ ... │ │
│ │ └────────┘ └────────┘ └────────┘ │ │
│ └──────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Business Logic │ │
│ │ 业务处理 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ 3. Offset 提交 │
│ ┌──────────┐ ┌──────────┐ │
│ │Consumer │ ──OffsetCommit───► │ Broker │ │
│ │ │ │(Coordinator) │
│ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
版本演进
Kafka 版本历程
| 版本 | 发布时间 | 重要特性 |
|---|---|---|
| 0.7 | 2011 | 开源发布 |
| 0.8 | 2013 | 副本机制、高可用 |
| 0.9 | 2015 | 安全特性、新Consumer API |
| 0.10 | 2016 | Kafka Streams、消息时间戳 |
| 0.11 | 2017 | 幂等生产者、事务支持 |
| 1.0 | 2017 | API 稳定化 |
| 1.1 | 2018 | Controller 改进、JBOD 支持 |
| 2.0 | 2018 | 前缀 ACL、KIP-290 |
| 2.1 | 2018 | ZStandard 压缩 |
| 2.4 | 2020 | 消费者增量 Rebalance |
| 2.5 | 2020 | TLS 改进、Transaction 改进 |
| 2.7 | 2021 | KRaft Early Access |
| 2.8 | 2021 | KRaft 生产预览 |
| 3.0 | 2021 | KRaft 默认可用、移除旧API |
| 3.1 | 2022 | KRaft 增强 |
| 3.3 | 2022 | KRaft 生产就绪 |
| 3.6 | 2023 | KIP-848 新消费者组协议 |
| 3.9 | 2024 | 持续优化增强 |
Kafka 3.x 核心特性
本系列基于 Kafka 3.9.x 版本讲解,重点介绍以下特性:
Kafka 3.x 核心特性:
├── KRaft 模式(取代 ZooKeeper)
│ ├── 内置共识协议
│ ├── 更简单的部署架构
│ └── 更好的扩展性
├── 新消费者组协议(KIP-848)
│ ├── 渐进式 Rebalance
│ ├── 更快的消费者组协调
│ └── 减少消费中断
├── 性能优化
│ ├── 更高效的日志压缩
│ ├── 改进的缓存策略
│ └── 更快的故障恢复
└── API 增强
├── AdminClient 增强
├── 新的配置选项
└── 更好的错误处理
技术选型建议
集群规模规划
┌─────────────────────────────────────────────────────────────────┐
│ 集群规模参考 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 小型集群(日处理 < 1亿条消息) │
│ ├── Broker 数量:3-5 │
│ ├── 每台配置:8C16G,SSD 500GB │
│ └── 适用场景:中小型企业、测试环境 │
│ │
│ 中型集群(日处理 1-10亿条消息) │
│ ├── Broker 数量:6-10 │
│ ├── 每台配置:16C32G,SSD 1TB │
│ └── 适用场景:大型企业、生产环境 │
│ │
│ 大型集群(日处理 > 10亿条消息) │
│ ├── Broker 数量:10+ │
│ ├── 每台配置:32C64G,SSD 2TB+ │
│ └── 适用场景:互联网大厂、数据密集型应用 │
│ │
└─────────────────────────────────────────────────────────────────┘
硬件配置建议
# 生产环境推荐配置
Broker:
CPU: 16核+(高吞吐场景建议24核+)
内存: 32GB+(主要供Page Cache使用)
磁盘: SSD,吞吐量>500MB/s
网络: 万兆网卡,带宽>10Gbps
JVM:
heap_size: 6-8GB(不建议超过32GB)
gc: G1GC
# 关键JVM参数
-XX:+UseG1GC
-XX:MaxGCPauseMillis=20
-XX:InitiatingHeapOccupancyPercent=35
-XX:+ExplicitGCInvokesConcurrent
操作系统:
# 文件描述符
nofile: 100000
# 最大打开文件数
fs.file-max: 1000000
# 网络参数
net.core.somaxconn: 32768
net.ipv4.tcp_max_syn_backlog: 16384
本系列学习路径
第一阶段:基础篇
├── 第1章:概述与架构设计(本章)
├── 第2章:消息模型与存储机制
└── 第3章:生产者核心原理
第二阶段:核心篇
├── 第4章:消费者核心原理
├── 第5章:Broker与副本机制
└── 第6章:消息可靠性保证
第三阶段:进阶篇
├── 第7章:高性能设计原理
└── 第8章:集群管理与运维
第四阶段:实战篇
└── 第9章:企业级实战案例
环境准备
安装 Kafka 3.9.x
# 下载 Kafka
wget https://archive.apache.org/dist/kafka/3.9.0/kafka_2.13-3.9.0.tgz
tar -xzf kafka_2.13-3.9.0.tgz
cd kafka_2.13-3.9.0
# KRaft 模式启动(推荐)
# 1. 生成集群ID
KAFKA_CLUSTER_ID=$(bin/kafka-storage.sh random-uuid)
# 2. 格式化存储目录
bin/kafka-storage.sh format -t $KAFKA_CLUSTER_ID -c config/kraft/server.properties
# 3. 启动服务
bin/kafka-server-start.sh config/kraft/server.properties
创建测试主题
# 创建主题
bin/kafka-topics.sh --create \
--topic test-topic \
--partitions 3 \
--replication-factor 1 \
--bootstrap-server localhost:9092
# 查看主题详情
bin/kafka-topics.sh --describe \
--topic test-topic \
--bootstrap-server localhost:9092
小结
本章我们学习了:
- Kafka 定义:高吞吐量分布式流处理平台
- 核心概念:Producer、Broker、Consumer、Topic、Partition、Offset
- 整体架构:发布-订阅模型、分区并行处理、副本容错机制
- 版本演进:从 ZooKeeper 到 KRaft 的架构升级
- 技术选型:集群规模规划、硬件配置建议
参考资料
- Apache Kafka 官方文档
- KIP-500: Replace ZooKeeper with a Self-Managed Metadata Quorum
- Kafka: The Definitive Guide
- Kafka 内部原理
下一章预告
在下一章《消息模型与存储机制》中,我们将深入探讨:
- Topic 与 Partition 的内部结构
- 消息格式与序列化机制
- 日志段(LogSegment)设计
- 索引机制与消息查找
Kafka 核心原理系列持续更新中,欢迎关注!