一、什么是 Kafka
Apache Kafka 是一个开源的分布式流处理平台,最初由 LinkedIn 开发,2011 年开源。它不仅仅是一个消息队列,更是一个集消息发布/订阅、持久化存储、实时流处理于一体的分布式系统。
简单来说,Kafka 就像是分布式系统的"数据高速公路"——各个系统通过它传输数据,既能异步解耦,又能保证高吞吐和可靠性。
Kafka 的三大核心能力:
| 能力 | 说明 |
|---|---|
| 发布与订阅 | 类似消息队列,生产者发送消息,消费者订阅消费 |
| 持久化存储 | 消息持久化到磁盘,可回溯、可重放,不会消费即删除 |
| 实时流处理 | 通过 Kafka Streams / ksqlDB 实现实时计算 |
核心设计目标:
- 高吞吐:单集群轻松支持百万级消息/秒
- 低延迟:毫秒级端到端延迟
- 可扩展:水平扩展,增加 Broker 即可提升容量
- 持久化:消息可保留数天甚至永久,支持重复消费
- 容错性:副本机制保证数据不丢失
二、核心概念
理解 Kafka,首先要理解以下核心概念:
| 概念 | 说明 |
|---|---|
| Broker | Kafka 集群中的一个节点,负责消息的存储和转发 |
| Topic | 消息的逻辑分类,生产者按 Topic 发布消息,消费者按 Topic 订阅 |
| Partition | Topic 的物理分区,是分布式存储和并行处理的基本单元 |
| Replica | Partition 的副本,分为 Leader(处理读写)和 Follower(同步数据) |
| Offset | 消息在 Partition 中的唯一偏移量,标识消费进度 |
| Consumer Group | 消费者组,组内消费者共同消费一个 Topic 的不同 Partition |
| ISR | In-Sync Replicas,与 Leader 保持同步的副本集合 |
关键理解:
- 一个 Topic 可以有多个 Partition,分布在不同的 Broker 上
- 每个 Partition 内部消息有序,跨 Partition无序
- 一个 Partition 只能被同一个 Consumer Group 内的一个 Consumer消费
- 不同的 Consumer Group 之间互不影响,可以独立消费同一个 Topic
三、架构原理
3.1 数据流转过程
Kafka 的数据流转非常清晰:
Producer → Broker 集群 → Consumer Group- 生产者发送消息:Producer 将消息发送到指定 Topic,Kafka 根据分区策略(如 Key Hash)将消息路由到具体的 Partition
- Broker 存储消息:消息被追加写入 Partition 的日志文件(顺序写入),同时 Follower 副本从 Leader 同步数据
- 消费者拉取消息:Consumer 从 Partition 的 Leader 副本拉取消息,处理完成后提交 Offset
3.2 分区机制
Partition 是 Kafka 实现水平扩展和并行处理的核心:
Topic: order-topic ├── Partition-0 (Broker-1) ├── Partition-1 (Broker-2) └── Partition-2 (Broker-3)分区的关键特性:
| 特性 | 说明 |
|---|---|
| 分区内有序 | 同一 Partition 的消息按 Offset 严格有序 |
| 分区间无序 | 不同 Partition 之间没有顺序保证 |
| 水平扩展 | 增加 Partition 数量可线性提升吞吐量 |
| 并行消费 | 多个 Consumer 可并行消费不同 Partition |
分区数与消费者数的关系:
- 消费者数 ≤ Partition 数:部分消费者消费多个 Partition
- 消费者数 = Partition 数:最佳并行度
- 消费者数 > Partition 数:部分消费者空闲(浪费资源)
3.3 副本机制与 ISR
每个 Partition 可以有多个副本(Replica),分布在不同的 Broker 上:
Partition-0 ├── Leader (Broker-1) ← 处理所有读写请求 ├── Follower-1 (Broker-2) ← 同步 Leader 数据 └── Follower-2 (Broker-3) ← 同步 Leader 数据ISR(In-Sync Replicas):
- ISR 是与 Leader 保持同步的副本集合
- 同步判定标准:在
replica.lag.time.max.ms(默认 30s)内未落后 Leader - 只有 ISR 中的副本才有资格在 Leader 故障时被选举为新 Leader
数据写入流程:
1. Producer 发送消息到 Leader 2. Leader 写入本地日志 3. Follower 从 Leader 拉取并写入本地 4. Follower 向 Leader 返回 ACK 5. Leader 收到 ISR 中过半副本的 ACK 后,向 Producer 返回成功3.4 Leader 选举
当 Leader 副本所在 Broker 宕机时,Kafka 会从 ISR 中选举新的 Leader:
- Controller 检测到 Leader 失效
- 从 ISR 中选择一个新的副本作为 Leader
- 通知所有相关 Broker 更新元数据
- Producer 和 Consumer 自动重定向到新 Leader
四、为什么 Kafka 这么快
Kafka 能够实现百万级 TPS,依赖以下核心设计:
4.1 顺序写入
Kafka 将消息追加写入磁盘(Append-Only),避免了随机 I/O:
磁盘顺序写入速度 ≈ 内存随机写入速度 >> 磁盘随机写入速度4.2 零拷贝(Zero-Copy)
传统数据传输:磁盘 → 内核缓冲区 → 用户空间 → Socket 缓冲区 → 网卡(4次拷贝)
Kafka 使用sendfile()系统调用:磁盘 → 内核缓冲区 → 网卡(2次拷贝)
4.3 页缓存(Page Cache)
Kafka 不自己管理内存,而是利用操作系统的 Page Cache:
- 消息写入时直接进入 Page Cache,由 OS 异步刷盘
- 消息读取时优先从 Page Cache 读取,命中率高
4.4 批量与压缩
- 批量发送:Producer 可以攒一批消息后一次性发送
- 批量压缩:支持 Snappy、LZ4、Zstd 等压缩算法,减少网络传输
4.5 分段存储
每个 Partition 由多个 Log Segment 组成:
partition-0/ ├── 00000000000000000000.log ← 第 0 ~ 1000 条消息 ├── 00000000000000000000.index ← 偏移量索引 ├── 00000000000000000000.timeindex← 时间戳索引 ├── 00000000000000368769.log ← 第 1001 ~ 2000 条消息 └── ...- 每个 Segment 默认 1GB,便于管理和清理
- 通过稀疏索引快速定位消息
五、消费者组与 Rebalance
5.1 消费者组机制
Consumer Group 是 Kafka 实现并行消费和消息广播的核心:
Topic: order-topic (3 Partitions) Consumer Group A (订单处理): ├── Consumer-A1 → Partition-0 ├── Consumer-A2 → Partition-1 └── Consumer-A3 → Partition-2 Consumer Group B (数据分析): ├── Consumer-B1 → Partition-0 ├── Consumer-B2 → Partition-1 └── Consumer-B3 → Partition-2- 同一个 Group 内:一个 Partition 只能被一个 Consumer 消费(负载均衡)
- 不同 Group 之间:每个 Group 都能消费完整的 Topic(消息广播)
5.2 Rebalance(再平衡)
当 Consumer Group 中的成员发生变化时,会触发 Rebalance:
触发条件:
- 新 Consumer 加入 Group
- Consumer 宕机或主动退出
- Consumer 心跳超时(
session.timeout.ms) - 消费处理超时(
max.poll.interval.ms) - Topic 分区数变化
分区分配策略:
| 策略 | 说明 |
|---|---|
| Range | 按分区序号范围分配(默认) |
| RoundRobin | 轮询分配所有分区 |
| Sticky | 粘性分配,最小化重平衡时的分区移动 |
| CooperativeSticky | 协作式粘性分配,避免全量停止 |
注意:Rebalance 期间 Consumer 无法消费消息,频繁 Rebalance 会影响性能。
六、常见应用场景
6.1 日志收集
Kafka 最初就是为日志收集而生的。将各个服务的日志统一发送到 Kafka,再由下游系统处理:
App Logs → Kafka (log-topic) → Elasticsearch → Kibana ↓ Hive (离线分析)优势:
- 解耦日志产生与存储
- 高吞吐应对突发流量
- 日志可重放(修复 ETL 逻辑后重新导入)
6.2 异步解耦与削峰填谷
将耗时操作异步化,主流程无需等待:
用户下单 → 订单服务 → Kafka (order-topic) ├── 库存服务(扣减库存) ├── 积分服务(发放积分) └── 通知服务(发送短信/邮件)优势:
- 主流程响应时间缩短
- 下游系统按需消费,避免被流量冲垮
- 系统间完全解耦,独立扩展
6.3 实时数据管道(ETL)
Kafka 作为数据管道的中心,连接各个数据源和数据目的地:
MySQL (CDC) → Debezium → Kafka → Kafka Streams → ClickHouse / S3 ↓ Flink (实时计算)优势:
- 统一的数据入口和出口
- 支持多种数据源和数据目的地
- 数据可回溯、可重放
6.4 流式处理
结合 Kafka Streams 或 Flink,实现实时数据处理:
// 实时统计每小时订单金额KStream<String,OrderEvent>orders=builder.stream("db.orders");KTable<Windowed<String>,Double>hourlyRevenue=orders.filter((k,v)->v.getStatus().equals("PAID")).groupBy((k,v)->v.getStoreId()).windowedBy(TimeWindows.of(Duration.ofHours(1))).aggregate(()->0.0,(storeId,order,total)->total+order.getAmount());典型应用:
- 实时排行榜
- 实时风控
- 实时监控告警
- 实时用户画像
6.5 事件驱动架构
在微服务架构中,服务间通过事件通信:
订单服务 → [订单创建事件] → Kafka ├── 库存服务 → [库存扣减事件] ├── 支付服务 → [支付完成事件] └── 物流服务 → [发货事件]优势:
- 服务间完全解耦
- 支持事件溯源(Event Sourcing)
- 最终一致性保证
七、分布式安装部署
1. 集群规划
在已有的hadoop1、hadoop2、hadoop3上部署 kafka_2.12-3.5.1
2. 下载安装
- 下载地址:https://kafka.apache.org/community/downloads/#351
下载完后上传到
/opt/software目录,再 tar 解压到/opt/module:cd /opt/software tar -zxvf kafka_2.12-3.5.1.tgz -C /opt/module/
3. 配置和分发
- 进入解压目录,修改配置文件
server.properties
cd/opt/module/kafka_2.12-3.5.1/config/vimserver.properties- 输入下面内容,注意先注释掉已有的同名配置
#broker的全局唯一编号,不能重复,只能是数字。broker.id=1#broker对外暴露的IP和端口 (每个节点单独配置)advertised.listeners=PLAINTEXT://hadoop1:9092#处理网络请求的线程数量num.network.threads=3#用来处理磁盘IO的线程数量num.io.threads=8#发送套接字的缓冲区大小socket.send.buffer.bytes=102400#接收套接字的缓冲区大小socket.receive.buffer.bytes=102400#请求套接字的缓冲区大小socket.request.max.bytes=104857600#kafka运行日志(数据)存放的路径,路径不需要提前创建,kafka自动帮你创建,可以配置多个磁盘路径,路径与路径之间可以用","分隔log.dirs=/opt/module/kafka_2.12-3.5.1/datas#topic在当前broker上的分区个数num.partitions=1#用来恢复和清理data下数据的线程数量num.recovery.threads.per.data.dir=1# 每个topic创建时的副本数,默认时1个副本offsets.topic.replication.factor=1#segment文件保留的最长时间,超时将被删除log.retention.hours=168#每个segment文件的大小,默认最大1Glog.segment.bytes=1073741824# 检查过期数据的时间,默认5分钟检查一次是否数据过期log.retention.check.interval.ms=300000#配置连接Zookeeper集群地址(在zk根目录下创建/kafka,方便管理)zookeeper.connect=hadoop1:2181,hadoop2:2181,hadoop3:2181/kafka分发安装包
cd/opt/module xsync kafka_2.12-3.5.1分别在其它hadoop2、hadoop3修改配置文件
server.properties中的broker.id和advertised.listeners,不能重复
6. 配置环境变量
sudovim/etc/profile.d/my_env.sh在文件末尾增加如下内容:
#KAFKA_HOMEexportKAFKA_HOME=/opt/module/kafka_2.12-3.5.1exportPATH=$PATH:$KAFKA_HOME/bin分发环境变量文件,再刷新环境变量
sudo/home/hadoop/bin/xsync /etc/profile.d/my_env.shsource/etc/profile4. 集群启停脚本
- 在
/home/hadoop/bin目录下创建脚本
cd~/binvimkf.sh输入如下内容:
#! /bin/bashcase$1in"start"){foriinhadoop1 hadoop2 hadoop3doecho" --------启动$iKafka-------"ssh$i"/opt/module/kafka_2.12-3.5.1/bin/kafka-server-start.sh -daemon /opt/module/kafka_2.12-3.5.1/config/server.properties"done};;"stop"){foriinhadoop1 hadoop2 hadoop3doecho" --------停止$iKafka-------"ssh$i"/opt/module/kafka_2.12-3.5.1/bin/kafka-server-stop.sh "done};;esac- 增加执行权限,起停集群,kafka依赖zookeeper服务,必须先启动zookeeper
chmod+x kf.sh zk.sh start kf.sh start kf.sh stop zk.sh stop八、 常用终端命令
1. 服务启停命令
| 脚本名称 | 完整示例命令 | 功能作用 |
|---|---|---|
| kafka-server-start.sh | bin/kafka-server-start.sh config/server.properties | 前台启动 Kafka Broker 服务 |
| kafka-server-stop.sh | bin/kafka-server-stop.sh | 优雅关闭 Kafka 服务 |
| zookeeper-server-start.sh | bin/zookeeper-server-start.sh config/zookeeper.properties | 启动内置 Zookeeper(KRaft 版本无需) |
| zookeeper-server-stop.sh | bin/zookeeper-server-stop.sh | 关闭内置 Zookeeper |
2. Topic 主题管理
| 脚本名称 | 完整示例命令 | 功能作用 |
|---|---|---|
| kafka-topics.sh | 创建 Topicbin/kafka-topics.sh --create --bootstrap-server 127.0.0.1:9092 --topic test_topic --partitions 3 --replication-factor 2 | 创建主题,指定分区、副本数 |
| kafka-topics.sh | 查看所有 Topicbin/kafka-topics.sh --list --bootstrap-server 127.0.0.1:9092 | 列出集群全部主题 |
| kafka-topics.sh | 查看 Topic 详情bin/kafka-topics.sh --describe --bootstrap-server 127.0.0.1:9092 --topic test_topic | 查看分区 Leader、副本、ISR 同步列表 |
| kafka-topics.sh | 扩容分区bin/kafka-topics.sh --alter --bootstrap-server 127.0.0.1:9092 --topic test_topic --partitions 5 | 增加分区(不支持减少分区) |
| kafka-topics.sh | 删除 Topicbin/kafka-topics.sh --delete --bootstrap-server 127.0.0.1:9092 --topic test_topic | 删除主题,需开启delete.topic.enable=true |
3. 控制台生产者(发送消息)
| 脚本名称 | 完整示例命令 | 功能作用 |
|---|---|---|
| kafka-console-producer.sh | bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic test_topic | 简易控制台发送普通消息 |
| kafka-console-producer.sh | 带 Key 发送bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic test_topic --property parse.key=true --property key.separator=, | 发送带消息 Key 的数据,逗号分隔 key/value |
4. 控制台消费者(消费消息)
| 脚本名称 | 完整示例命令 | 功能作用 |
|---|---|---|
| kafka-console-consumer.sh | bin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic test_topic | 实时消费新产生消息 |
| kafka-console-consumer.sh | bin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic test_topic --from-beginning | 从头消费该 Topic 所有历史消息 |
| kafka-console-consumer.sh | 指定消费组bin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic test_topic --group test_group | 使用自定义消费组,持久化 offset |
| kafka-console-consumer.sh | 打印 Key+Valuebin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic test_topic --from-beginning --property print.key=true --property key.separator=: | 消费时同时输出消息 Key 与 Value |
5. 消费组 & Offset 偏移量管理
| 脚本名称 | 完整示例命令 | 功能作用 |
|---|---|---|
| kafka-consumer-groups.sh | 查看全部消费组bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --list | 列出集群内所有消费组名称 |
| kafka-consumer-groups.sh | 查看消费组详情bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --group test_group --describe | 查看分区 offset、消息堆积 LAG、分配节点 |
| kafka-consumer-groups.sh | 重置 offset 到最早bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --group test_group --topic test_topic --reset-offsets --to-earliest --execute | 偏移量重置至分区第一条消息(需停消费程序) |
| kafka-consumer-groups.sh | 重置 offset 到最新bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --group test_group --topic test_topic --reset-offsets --to-latest --execute | 偏移量重置至最新消息,跳过历史数据 |
| kafka-consumer-groups.sh | 删除消费组bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --group test_group --delete | 删除无活跃消费者、无 offset 的空消费组 |
九、Kafka 与其他消息队列对比
| 对比维度 | Kafka | RabbitMQ | RocketMQ |
|---|---|---|---|
| 定位 | 分布式流平台 | 传统消息队列 | 金融级消息队列 |
| 吞吐量 | 百万级/秒 | 万级/秒 | 十万级/秒 |
| 延迟 | 毫秒级 | 微秒级 | 毫秒级 |
| 消息留存 | 支持(可配置保留时间) | 消费即删除 | 支持 |
| 顺序保证 | Partition 内有序 | 单队列有序 | 队列内有序 |
| 协议 | 自定义二进制 | AMQP | 自定义 |
| 适用场景 | 日志、事件流、流处理 | 任务队列、RPC | 金融、电商 |
选型建议:
- 要高吞吐、可重放、流处理 →Kafka
- 要低延迟、复杂路由、AMQP →RabbitMQ
- 要金融级可靠、事务消息 →RocketMQ
十、总结
Kafka 的核心价值可以用一句话概括:高吞吐 + 持久化 + 流处理。
| 核心能力 | 支撑的应用场景 |
|---|---|
| 高吞吐、低延迟 | 日志收集、实时数据管道 |
| 持久化存储 | 消息重放、事件溯源 |
| 分区并行 | 水平扩展、并行消费 |
| 副本机制 | 数据可靠性、高可用 |
| 消费者组 | 负载均衡、消息广播 |
| Kafka Streams | 实时流处理 |
Kafka 已经成为现代分布式系统的标配基础设施,尤其在大数据、实时计算、微服务架构中扮演着核心角色。
参考资源:
- Apache Kafka 官方文档
- Kafka 设计原理