Kafka 从入门到精通 — 完整学习笔记

Kafka 从入门到精通 --- 完整学习笔记

服务器环境 :华为云 ecs-7c2c x 4 台 | Ubuntu 24.04 | 2vCPU/4GiB

Kafka 版本 :4.3.0 | Scala 2.13 | KRaft 模式(无 ZooKeeper)

集群架构 :3 Controller + 1 Broker | 内网互联 192.168.0.x

集群 UUID :1S9ggrMYQaCHBqfZy8hhOg

实战日期:2026-06-01


目录

  1. [第一章:Kafka 基础入门](#第一章:Kafka 基础入门)
  2. [第二章:Kafka 安装与配置](#第二章:Kafka 安装与配置)
  3. [第三章:Kafka 核心 API 详解](#第三章:Kafka 核心 API 详解)
  4. [第四章:Kafka 核心机制深入](#第四章:Kafka 核心机制深入)
  5. [第五章:Kafka 生产者详解](#第五章:Kafka 生产者详解)
  6. [第六章:Kafka 消费者详解](#第六章:Kafka 消费者详解)
  7. [第七章:Kafka 集群管理](#第七章:Kafka 集群管理)
  8. [第八章:Kafka 安全机制](#第八章:Kafka 安全机制)
  9. [第九章:Kafka Streams 与 KSQL](#第九章:Kafka Streams 与 KSQL)
  10. [第十章:Kafka Connect 数据集成](#第十章:Kafka Connect 数据集成)
  11. [第十一章:Kafka 性能优化](#第十一章:Kafka 性能优化)
  12. [第十二章:Kafka 运维与故障排查](#第十二章:Kafka 运维与故障排查)
  13. [第十三章:Kafka 实战项目案例](#第十三章:Kafka 实战项目案例)
  14. [第十四章:Kafka 新特性与未来](#第十四章:Kafka 新特性与未来)
  15. [第十五章:Kafka 面试与进阶](#第十五章:Kafka 面试与进阶)
  16. 附录

第一章:Kafka 基础入门

1.1 消息队列与 Kafka 概述

1.1.1 消息队列概念与作用

消息队列(Message Queue) 是一种异步通信中间件,允许应用程序通过发送和接收消息来进行通信,而不需要彼此同时在线。

复制代码
┌──────────────────────────────────────────────────────────────────┐
│                      消息队列核心价值                               │
│                                                                  │
│   [Producer A] ──┐                      ┌── [Consumer X]         │
│                  │                      │                        │
│   [Producer B] ──┼──► [Message Queue] ──┼── [Consumer Y]         │
│                  │                      │                        │
│   [Producer C] ──┘                      └── [Consumer Z]         │
│                                                                  │
│   解耦:生产者和消费者独立演进                                       │
│   削峰:应对流量突增,保护下游系统                                    │
│   异步:非阻塞通信,提升系统响应速度                                  │
│   可靠:消息持久化,保证不丢失                                       │
│   顺序:支持消息顺序性保证                                          │
└──────────────────────────────────────────────────────────────────┘

为什么需要消息队列:

问题 无消息队列 有消息队列
系统耦合 服务直接调用,一方故障全链路阻塞 服务通过消息通信,独立部署
流量冲击 秒杀场景 10000 QPS 直接打崩数据库 消息队列缓冲,后端按能力消费
数据丢失 服务故障,请求数据丢失 消息持久化到磁盘,故障恢复后可消费
扩展性 消费端扩容需要修改上游 消费者组支持动态增减实例
协议适配 异构系统直连需要统一协议 消息队列屏蔽协议差异
1.1.2 消息队列模式

点对点模式(Point-to-Point / Queue):

复制代码
[Producer] ──► [Queue] ──► [Consumer A]
               消息被一个消费者消费后即删除
  • 一条消息只能被一个消费者消费
  • 消费者消费后消息从队列删除
  • 多个消费者可共享消费负载(竞争消费)
  • 典型代表:RabbitMQ(Work Queue)

发布订阅模式(Publish-Subscribe / Topic):

复制代码
                    ┌── [Subscriber A]
[Publisher] ──► [Topic] ──┼── [Subscriber B]
                    └── [Subscriber C]
               一条消息可以被多个订阅者消费
  • 一条消息可以被多个消费者(订阅者)消费
  • 消费者需要提前订阅 Topic
  • 消息被所有订阅者消费后才删除
  • Kafka 本质上是发布订阅模式的分布式实现
1.1.3 Kafka 定义与特点

Apache Kafka 是一个分布式流处理平台,具有以下核心能力:

复制代码
Kafka 三大定位:

1. 消息队列 --- 高吞吐、低延迟的消息传递系统
   发布 & 订阅消息流,类似消息队列或企业消息系统

2. 存储系统 --- 持久化、容错的分布式日志存储
   以容错、持久的方式存储消息流

3. 流处理 --- 实时处理消息流
   在消息流产生时即对其进行处理

Kafka 核心特点:

特性 说明 实战数据
高吞吐 单 Broker 可达数十万 msg/s 本次 ~13K msg/s(2vCPU/4GiB 受限)
低延迟 P50 延迟 < 10ms(本地网络) 本次 P50 = 56ms(跨公网 ECS)
持久化 消息写入磁盘,零拷贝读取 日志段(Log Segment)持久化
水平扩展 Broker 动态增减,分区重新分配 4 Broker 集群,在线扩容
容错 副本机制,ISR 自动故障转移 RF=3,min.insync.replicas=2
顺序保证 分区内消息严格有序 Key 路由验证:同一 Key 固定分区
多客户端 Java/Python/Go/C++/Rust 等 Java 官方 + kafka-python 验证通过
1.1.4 Kafka 发展历程与版本演进
复制代码
2010 --- LinkedIn 开发 Kafka,用于活动流数据管道
2011 --- Apache 孵化器项目,0.7 版本发布
2012 --- Apache 顶级项目,0.8 版本(引入副本机制)
2014 --- 0.8.2 版本(日志压缩)
2015 --- 0.9.0 版本(安全特性 SSL/SASL)
2016 --- 0.10.0 版本(Kafka Streams)
2017 --- 0.11.0 版本(Exactly-Once 语义、事务)
2018 --- 1.0.0 / 2.0.0(性能优化、JMX 监控增强)
2019 --- 2.3.0(增量消费者组再均衡)
2020 --- 2.6.0(KRaft 早期预览)
2021 --- 2.8.0(KRaft 可用于生产)
2022 --- 3.3.0(KRaft 生产就绪)
2023 --- 3.6.0(Tiered Storage 早期预览)
2024 --- 3.7.0 / 3.8.0(KRaft ZooKeeper 弃用)
2025 --- 3.9.0(KRaft 模式优化)
2026 --- **4.3.0(完全 KRaft,无 ZK 代码)← 当前版本**

版本选择建议:

版本线 ZK 依赖 KRaft 推荐场景
< 2.8 必须 不可用 存量老系统
2.8 - 3.2 可选 预览 测试环境尝鲜
3.3 - 3.9 可选 生产就绪 过渡期,可双模式
4.x 已移除 唯一模式 新项目首选
1.1.5 Kafka 应用场景
复制代码
┌─────────────────────────────────────────────────────────────────┐
│                     Kafka 典型应用场景                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. 日志收集 (Log Aggregation)                                   │
│     App Logs → Filebeat → Kafka → Logstash → Elasticsearch      │
│                                                                 │
│  2. 流处理 (Stream Processing)                                   │
│     Events → Kafka → Kafka Streams / Flink → 实时大盘            │
│                                                                 │
│  3. 事件溯源 (Event Sourcing)                                     │
│     所有状态变更作为事件流存入 Kafka,可回溯重建任意时刻状态          │
│                                                                 │
│  4. 消息系统 (Messaging)                                         │
│     微服务间异步通信,解耦服务依赖                                  │
│                                                                 │
│  5. 指标收集 (Metrics)                                           │
│     系统指标 → Kafka → Prometheus / InfluxDB                     │
│                                                                 │
│  6. CDC 数据同步 (Change Data Capture)                            │
│     MySQL Binlog → Debezium → Kafka → 数据仓库/Hadoop            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

1.2 Kafka 与竞品对比

1.2.1 Kafka vs RabbitMQ
维度 Kafka RabbitMQ
设计理念 分布式日志 (append-only log) 消息代理 (AMQP 协议)
吞吐量 极高(百万级/秒) 中等(万级/秒)
消息持久化 默认持久化到磁盘 可选持久化(内存/磁盘)
消费者模型 Pull 拉取模式 Push 推送模式
消息回溯 支持(保留期内任意 offset 回放) 不支持
分区 核心概念,分区内有序 无分区(Exchange + Queue)
路由灵活性 简单(Topic → Partition) 复杂(Exchange + Routing Key + Binding)
协议 自定义二进制协议 AMQP 0-9-1
事务支持 支持(Exactly-Once) 部分支持
适用场景 大数据管道、流处理、事件驱动 传统消息队列、RPC 调用、任务队列
1.2.2 Kafka vs RocketMQ
维度 Kafka RocketMQ
开发语言 Java/Scala Java
社区 Apache 顶级项目,全球社区 阿里开源,国内生态强
事务消息 支持(幂等 + 事务) 原生支持(半消息机制)
延迟消息 需自行实现 原生支持 18 个延迟级别
消息过滤 客户端侧过滤 Broker 侧 SQL 过滤
重试机制 需自行实现 内置消费重试 + 死信队列
顺序消息 分区内有序 分区内有序(支持全局有序)
适用场景 大数据/流处理场景 电商/金融业务消息
1.2.3 Kafka vs Pulsar
维度 Kafka Pulsar
架构 Broker 一体(计算+存储绑定) 计算存储分离(Broker + BookKeeper)
多租户 有限(通过 Topic 前缀) 原生多租户(Tenant/Namespace)
Geo-Replication MirrorMaker 2 原生跨地域复制
消息确认 Offset 提交 单条消息确认(Ack)
队列模式 通过 Consumer Group 模拟 原生支持 Queue + Stream
分层存储 4.x Tiered Storage 原生 Tiered Storage
运维复杂度 较低 较高(BookKeeper + ZooKeeper)
1.2.4 Kafka vs ActiveMQ
维度 Kafka ActiveMQ
吞吐量 极高 中等偏低
协议支持 自定义 多协议(AMQP/MQTT/STOMP/OpenWire)
持久化 基于日志段 基于 KahaDB/JDBC
集群 原生分布式 Broker 网络(Network of Brokers)
现代性 活跃开发,4.x 持续迭代 Classic 已停维,Artemis 活跃
1.2.5 选型建议
复制代码
选 Kafka 如果:
  ✓ 需要高吞吐(百万 msg/s 级别)
  ✓ 需要消息回溯能力(Event Sourcing)
  ✓ 需要流处理(Kafka Streams / KSQL)
  ✓ 已有大数据生态(Hadoop/Spark/Flink)
  ✓ 团队熟悉 Java/Scala 生态

选 RocketMQ 如果:
  ✓ 需要事务消息(分布式事务场景)
  ✓ 需要定时/延迟消息
  ✓ 国内主流互联网公司环境
  ✓ 需要更丰富的消息模型

选 RabbitMQ 如果:
  ✓ 需要灵活的路由规则
  ✓ 需要低延迟(微秒级 RPC)
  ✓ 团队熟悉 AMQP 协议
  ✓ 消息量不高(万级/秒以下)

选 Pulsar 如果:
  ✓ 需要计算存储分离
  ✓ 需要原生多租户
  ✓ 需要队列 + 流双模式

1.3 Kafka 核心概念

1.3.1 概念全景图
复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                      Kafka 核心概念全景                               │
│                                                                     │
│  ┌──────────────┐                              ┌──────────────┐     │
│  │   Producer   │                              │   Consumer   │     │
│  │  生产者       │                              │  消费者       │     │
│  │  (push data) │                              │  (pull data) │     │
│  └──────┬───────┘                              └──────┬───────┘     │
│         │ send(message, topic, [key])                 │ poll()      │
│         ▼                                            │             │
│  ┌───────────────────────────────────────────────────▼──────────┐  │
│  │                      Kafka Cluster                            │  │
│  │                                                               │  │
│  │  ┌─────────────────────────────────────────────────────────┐ │  │
│  │  │  Topic: "orders"                     Partition Count: 4  │ │  │
│  │  │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐   │ │  │
│  │  │  │Partition0│ │Partition1│ │Partition2│ │Partition3│   │ │  │
│  │  │  │ 0 1 2 3..│ │ 0 1 2 3..│ │ 0 1 2 3..│ │ 0 1 2 3..│   │ │  │
│  │  │  │ (Leader) │ │ (Leader) │ │ (Leader) │ │ (Leader) │   │ │  │
│  │  │  │ Broker 1 │ │ Broker 2 │ │ Broker 3 │ │ Broker 4 │   │ │  │
│  │  │  └──────────┘ └──────────┘ └──────────┘ └──────────┘   │ │  │
│  │  └─────────────────────────────────────────────────────────┘ │  │
│  │                                                               │  │
│  │  Broker 1 ─ Broker 2 ─ Broker 3 ─ Broker 4                  │  │
│  │  (Controller)                                              │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                     │
│  Consumer Group "order-processor"                                   │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                        │
│  │Consumer A│  │Consumer B│  │Consumer C│                        │
│  │P0, P1    │  │P2        │  │P3        │                        │
│  └──────────┘  └──────────┘  └──────────┘                        │
│  每个分区只被组内一个消费者消费                                        │
└─────────────────────────────────────────────────────────────────────┘
1.3.2 核心概念详解

Topic(主题)

复制代码
Topic 是消息的逻辑分类,类似于数据库的"表"概念。
生产者将消息发送到特定 Topic,消费者从 Topic 订阅消息。

实战示例:
  Topic: test-basic    --- 基础功能测试
  Topic: test-compact  --- 压缩策略测试
  Topic: test-perf     --- 性能压测
  Topic: __consumer_offsets --- 消费者偏移量内部主题

Partition(分区)

复制代码
Topic 在物理上被分割为多个 Partition,每个 Partition 是一个有序、不可变的消息序列。

┌──────────────────────────────────────────────┐
│  Partition 0: [msg0] [msg1] [msg2] [msg3]... │
│  Partition 1: [msg0] [msg1] [msg2]...        │
│  Partition 2: [msg0] [msg1] [msg2]...        │
│  Partition 3: [msg0] [msg1] [msg2] [msg3]... │
└──────────────────────────────────────────────┘

分区的作用:
1. 水平扩展 --- 单个 Topic 可跨多台 Broker 存储
2. 并行消费 --- 多个消费者可并行消费不同分区
3. 顺序保证 --- 分区内消息严格有序(按 offset)

实战验证 --- Key 分区路由:

复制代码
# Python Producer 发送 10 条消息,按 user-{0,1,2} 作为 Key
Sent: key=user-0 → partition=3, offset=0
Sent: key=user-1 → partition=0, offset=10
Sent: key=user-2 → partition=0, offset=11
Sent: key=user-0 → partition=3, offset=1   ← 同一 Key 回同一分区!
Sent: key=user-1 → partition=0, offset=12
Sent: key=user-2 → partition=0, offset=13
Sent: key=user-0 → partition=3, offset=2
Sent: key=user-1 → partition=0, offset=14
Sent: key=user-2 → partition=0, offset=15
Sent: key=user-0 → partition=3, offset=3

结论:相同 Key 的消息一定进入同一个 Partition,保证该 Key 的消息顺序性。
      分区算法:partition = hash(key) % num_partitions

Broker(代理)

复制代码
Broker 是 Kafka 服务器节点,负责消息存储、请求处理、副本管理。

实战集群 (4 Brokers):
  Broker 1 (kafka-01) --- node.id=1, Controller + Broker
  Broker 2 (kafka-02) --- node.id=2, Controller + Broker
  Broker 3 (kafka-03) --- node.id=3, Controller + Broker
  Broker 4 (kafka-04) --- node.id=4, Broker Only (Observer)

Producer(生产者)

复制代码
Producer 负责将消息发送到指定的 Topic。

Producer 发送流程:
  1. 序列化 Key 和 Value
  2. 选择目标分区(Key Hash / Round-Robin / 自定义)
  3. 消息进入 RecordAccumulator 缓冲区
  4. Sender 线程批量发送到 Broker
  5. 等待 Broker 确认(根据 acks 配置)

关键参数:
  - acks=0:不等待确认,最快但可能丢失
  - acks=1:等待 Leader 确认
  - acks=all:等待所有 ISR 确认,最安全

Consumer(消费者)

复制代码
Consumer 从 Broker 拉取(Pull)消息进行处理。

关键行为:
  - 消费者主动拉取(非 Push),可自行控制消费速度
  - 消费者属于某个 Consumer Group
  - 通过 Offset 记录消费位置
  - 支持从任意 Offset 开始消费(earliest/latest/指定)

Consumer Group(消费者组)

复制代码
Consumer Group 是 Kafka 实现消息广播和单播的核心机制:

  - 一条消息可以被多个 Consumer Group 消费(广播)
  - 在一个 Group 内,一个 Partition 只能被一个 Consumer 消费(单播)

┌─────────────────────────────────────────────────────────┐
│  Group A (实时处理):  Consumer A1(P0,P1), A2(P2), A3(P3) │
│  Group B (离线分析):  Consumer B1(P0,P1,P2,P3)           │
│  Group C (监控告警):  Consumer C1(P0,P1,P2,P3)           │
│                                                         │
│  同一条消息被 3 个 Group 独立消费,互不影响                  │
└─────────────────────────────────────────────────────────┘

Offset(偏移量)

复制代码
Offset 是消息在 Partition 中的唯一递增编号,用于定位消息位置。

Partition 0: [msg(offset=0)] [msg(offset=1)] [msg(offset=2)] ...
                               ↑
                          消费者当前消费位置

Offset 管理方式:
  - 自动提交:enable.auto.commit=true(默认,5秒提交一次)
  - 手动同步提交:consumer.commitSync()
  - 手动异步提交:consumer.commitAsync()

Replica(副本)

复制代码
每个 Partition 有多个 Replica(副本):

  ┌──────────────────────────────────────────┐
  │  Partition 0: RF=3                       │
  │                                          │
  │  Broker 3: [Leader]    --- 处理读写请求     │
  │  Broker 4: [Follower]  --- 从 Leader 同步  │
  │  Broker 1: [Follower]  --- 从 Leader 同步  │
  │                                          │
  │  ISR (In-Sync Replicas): [3, 4, 1]      │
  │  HW  (High Watermark): 消费者可见最高偏移  │
  │  LEO (Log End Offset): 副本最新写入位置    │
  └──────────────────────────────────────────┘

实战验证:
  Topic: test-basic  Partition: 0  Leader: 3  Replicas: 3,4,1  Isr: 3,4,1
  Topic: test-basic  Partition: 1  Leader: 4  Replicas: 4,1,2  Isr: 4,1,2
  Topic: test-basic  Partition: 2  Leader: 1  Replicas: 1,2,3  Isr: 1,2,3
  Topic: test-basic  Partition: 3  Leader: 2  Replicas: 2,3,4  Isr: 2,3,4

  所有分区 ISR 完整,Leader 均匀分布在 4 个 Broker。✓

1.4 Kafka 架构设计

1.4.1 系统架构图
复制代码
┌──────────────────────────────────────────────────────────────────────┐
│                        Kafka 4.3.0 KRaft 架构                         │
│                                                                      │
│  ┌─────────────────── Controller Quorum ─────────────────────────┐  │
│  │                                                                │  │
│  │  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐       │  │
│  │  │  Broker 1    │   │  Broker 2    │   │  Broker 3    │       │  │
│  │  │  ID: 1       │   │  ID: 2       │   │  ID: 3       │       │  │
│  │  │  Controller  │◄──►  Controller  │◄──►  Controller  │       │  │
│  │  │  +           │   │  +           │   │  +           │       │  │
│  │  │  Broker      │   │  Broker      │   │  Broker      │       │  │
│  │  └──────┬───────┘   └──────┬───────┘   └──────┬───────┘       │  │
│  │         │                  │                  │                │  │
│  └─────────┼──────────────────┼──────────────────┼────────────────┘  │
│            │                  │                  │                   │
│            │         ┌────────┼──────────────────┼──────┐           │
│            │         │        │                  │      │           │
│            │         │   ┌────▼──────────────────▼──┐   │           │
│            │         │   │     Broker 4              │   │           │
│            │         │   │     ID: 4                 │   │           │
│            │         │   │     Broker Only           │   │           │
│            │         │   │     (Observer, 不参与选举) │   │           │
│            │         │   └───────────────────────────┘   │           │
│            │         │                                   │           │
│            ▼         ▼                                   ▼           │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                      Metadata Layer                             │  │
│  │  - Topic 元数据(分区、副本分配)                                 │  │
│  │  - Broker 注册信息                                               │  │
│  │  - Partition Leader 选举                                         │  │
│  │  - 基于 Raft 共识协议 (替代 ZooKeeper)                            │  │
│  └───────────────────────────────────────────────────────────────┘  │
│                                                                      │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                      Storage Layer                              │  │
│  │  /opt/kafka/data/                                              │  │
│  │    ├── test-basic-0/  (.log, .index, .timeindex)               │  │
│  │    ├── test-basic-1/                                           │  │
│  │    ├── test-basic-2/                                           │  │
│  │    ├── test-basic-3/                                           │  │
│  │    └── __consumer_offsets-*/                                    │  │
│  └───────────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────────┘
1.4.2 数据流架构
复制代码
                     Kafka 数据流

  ┌──────────┐       ┌──────────────────────┐       ┌──────────┐
  │ Producer │──1──►│    Kafka Cluster      │──3──►│ Consumer │
  │          │      │                      │      │          │
  │ 序列化    │      │  ┌────────────────┐  │      │ 反序列化  │
  │ 分区选择  │      │  │  Network Layer │  │      │ 拉取消息  │
  │ 批量发送  │      │  └───────┬────────┘  │      │ 处理消息  │
  │ 压缩      │      │          │            │      │ 提交Offset│
  └──────────┘      │  ┌───────▼────────┐  │      └──────────┘
                    │  │   API Layer    │  │
         2.写入请求  │  │ (KafkaApis)    │  │  4.拉取请求
                    │  └───────┬────────┘  │
                    │          │            │
                    │  ┌───────▼────────┐  │
                    │  │ Replica Manager│  │
                    │  │ (副本同步管理)   │  │
                    │  └───────┬────────┘  │
                    │          │            │
                    │  ┌───────▼────────┐  │
                    │  │  Log Manager   │  │
                    │  │ (磁盘持久化)      │  │
                    │  └────────────────┘  │
                    └──────────────────────┘
1.4.3 集群架构设计
复制代码
我们的实战集群 (4节点 KRaft):

┌──────────────────────────────────────────────────────────────┐
│  Controller Quorum (3节点, 多数派 = 2)                         │
│                                                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌──────────────┐ │
│  │   kafka-01      │  │   kafka-02      │  │   kafka-03   │ │
│  │   192.168.0.54  │  │   192.168.0.228 │  │ 192.168.0.89 │ │
│  │   node.id=1     │  │   node.id=2     │  │   node.id=3  │ │
│  │   Active Leader │  │   Follower      │  │   Follower   │ │
│  │   Controller ✓  │  │   Controller ✓  │  │  Controller ✓│ │
│  │   Broker ✓      │  │   Broker ✓      │  │  Broker ✓    │ │
│  └────────┬────────┘  └────────┬────────┘  └──────┬───────┘ │
│           │                    │                    │         │
│           └────────────────────┼────────────────────┘         │
│                                │                              │
│              ┌─────────────────▼──────────┐                   │
│              │       kafka-04             │                   │
│              │       192.168.0.128        │                   │
│              │       node.id=4            │                   │
│              │       Broker Only          │                   │
│              │       (Observer)            │                   │
│              └────────────────────────────┘                   │
└──────────────────────────────────────────────────────────────┘

Quorum 状态:
  ClusterId:              1S9ggrMYQaCHBqfZy8hhOg
  LeaderId:               1              ← kafka-01 是 Active Controller
  LeaderEpoch:            1
  HighWatermark:          192
  MaxFollowerLag:         0              ← 所有 Follower 完全同步
  CurrentVoters:          [1, 2, 3]
  CurrentObservers:       [4]            ← kafka-04 不参与 Controller 投票
1.4.4 ZooKeeper 的作用(Kafka 2.x 之前)
复制代码
ZooKeeper 在 Kafka 2.x 中的职责(已在新版本中移除):

  ┌─────────────────────────────────────────────────┐
  │              ZooKeeper Ensemble                  │
  │                                                 │
  │  1. Controller 选举                              │
  │     /controller → {"brokerid": 1}                │
  │                                                 │
  │  2. Broker 注册与发现                             │
  │     /brokers/ids/[0..N] → broker 信息             │
  │                                                 │
  │  3. Topic 配置管理                               │
  │     /brokers/topics/[topic_name] → 分区副本分配    │
  │                                                 │
  │  4. Partition Leader 选举                        │
  │     /brokers/topics/[topic]/partitions/[p]/state  │
  │                                                 │
  │  5. Consumer Group 协调 (旧版)                    │
  │     /consumers/[group]/offsets/[topic]/[partition] │
  │                                                 │
  │  6. ACL 权限存储                                  │
  │     /kafka-acl/                                  │
  └─────────────────────────────────────────────────┘

痛点(为什么抛弃 ZK):
  ✗ 运维复杂 --- 需要独立维护 ZooKeeper 集群
  ✗ 性能瓶颈 --- 元数据变更需写入 ZK,限制分区创建速度
  ✗ 一致性模型 --- ZK 和 Kafka 两个一致性系统协调困难
  ✗ 学习成本 --- 团队需要掌握两套系统
1.4.5 KRaft 模式(Kafka 3.x+,4.x 唯一模式)
复制代码
KRaft (Kafka Raft) 是 Kafka 自管理的共识协议,替代 ZK。

核心概念:

┌─────────────────────────────────────────────────────┐
│           KRaft Metadata Quorum                      │
│                                                     │
│  基于 Raft 协议:Leader + Follower                    │
│                                                     │
│  ┌──────────────┐                                   │
│  │ Quorum Leader │ ← Active Controller               │
│  │ 接收所有元数据变更  │                               │
│  │ 通过 Raft 复制到    │                               │
│  │ Follower 节点      │                               │
│  └──────┬───────┘                                   │
│         │ Raft Replication                           │
│    ┌────┼────┐                                      │
│    ▼    ▼    ▼                                      │
│  ┌────┐┌────┐┌────┐                                 │
│  │ F1 ││ F2 ││ F3 │ ← 需多数派确认 (N/2+1)            │
│  └────┘└────┘└────┘                                 │
│                                                     │
│  Metadata Topic: @metadata                            │
│  - 单一分区内部 Topic,存储所有集群元数据                │
│  - Leader Epoch 每次选举递增                          │
│  - 支持快照 (Snapshot) 压缩                           │
└─────────────────────────────────────────────────────┘

KRaft 优势:
  ✓ 架构简化 --- 无需维护 ZooKeeper 集群
  ✓ 性能提升 --- 元数据操作更快(无 ZK 写延迟)
  ✓ 运维简化 --- 单一系统,配置更少
  ✓ 扩展性 --- 支持更多分区(百万级→千万级)
  ✓ 启动速度 --- 无 ZK 连接等待,启动更快

实战配置:
  process.roles=broker,controller
  node.id=1
  controller.quorum.voters=1@192.168.0.54:9093,2@192.168.0.228:9093,3@192.168.0.89:9093
  controller.listener.names=CONTROLLER

第二章:Kafka 安装与配置

2.1 环境准备

2.1.1 系统要求
组件 最低要求 推荐配置 我们的实战配置
Java JDK 17+ JDK 21 OpenJDK 21.0.11
CPU 2 核 4 核+ 2 vCPU (ECS 基础型)
内存 2 GB (heap 1G) 8 GB+ (heap 6G) 4 GB (heap 1G)
磁盘 10 GB 100 GB+ SSD 40 GB 云盘
网络 1 Gbps 10 Gbps 华为云内网
文件描述符 100000 100000+ 默认 (1024)
操作系统 Linux 3.x+ Ubuntu 24.04 Ubuntu 24.04 LTS
2.1.2 网络配置要求
复制代码
Kafka 4.x KRaft 网络端口:

┌──────────────────────────────────────────────────┐
│  端口     │ 协议        │ 用途                     │
├───────────┼─────────────┼─────────────────────────┤
│  9092     │ PLAINTEXT   │ Broker 对外服务           │
│  9093     │ PLAINTEXT   │ Controller 内部通信       │
│  9094     │ SSL         │ SSL 加密外部访问 (可选)    │
│  9095     │ SASL_SSL    │ SASL+SSL 认证访问 (可选)  │
└──────────────────────────────────────────────────┘

实战配置(内网 + 公网):

  # 内网:Controller 通信,Broker 间数据同步
  listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093

  # 公网:Client 访问地址
  advertised.listeners=PLAINTEXT://<公网IP>:9092

  # Broker 间通信使用 PLAINTEXT listener
  inter.broker.listener.name=PLAINTEXT

  # Controller 通信使用 CONTROLLER listener
  controller.listener.names=CONTROLLER
2.1.3 操作系统优化
bash 复制代码
# 1. 文件描述符限制
ulimit -n 100000
# 持久化: /etc/security/limits.conf
# root soft nofile 100000
# root hard nofile 100000

# 2. 虚拟内存 (避免 OOM Killer)
sysctl -w vm.swappiness=1

# 3. 网络参数优化
sysctl -w net.core.rmem_default=1048576
sysctl -w net.core.wmem_default=1048576
sysctl -w net.ipv4.tcp_max_syn_backlog=4096

# 4. 磁盘挂载选项 (如使用独立数据盘)
# mount -o noatime /dev/vdb1 /opt/kafka/data

2.2 Linux 环境安装

2.2.1 下载与安装 Kafka 4.3.0
bash 复制代码
# 1. 安装 Java 21
sudo apt-get update
sudo apt-get install -y fontconfig openjdk-21-jre-headless
java -version
# openjdk version "21.0.11" 2026-04-21

# 2. 下载 Kafka (国内推荐阿里云镜像)
cd /opt
wget https://mirrors.aliyun.com/apache/kafka/4.3.0/kafka_2.13-4.3.0.tgz -O kafka.tgz
tar xzf kafka.tgz
mv kafka_2.13-4.3.0 kafka
rm kafka.tgz

# 3. 验证安装
ls /opt/kafka/bin/
# 共 44 个脚本文件
2.2.2 配置文件详解(server.properties)

完整配置及参数详解:

properties 复制代码
# ===== KRaft 模式核心配置 =====

# process.roles --- 节点角色
# 可选值: broker, controller, broker,controller
# broker: 仅存储数据,处理客户端请求
# controller: 参与元数据仲裁(Raft Quorum)
# broker,controller: 同时承担两种角色(推荐,简化部署)
process.roles=broker,controller

# node.id --- Broker 唯一标识
# 每个 Broker 必须有不同的 ID,范围 0 ~ N
# 对应 controller.quorum.voters 中的 ID
node.id=1

# controller.quorum.voters --- Controller 仲裁节点列表
# 格式: {id}@{host}:{port},{id}@{host}:{port},...
# 必须列出所有 Controller 节点,数量应为奇数(3 或 5)
# 多数派 = N/2 + 1,3 节点可容忍 1 台故障
controller.quorum.voters=1@192.168.0.54:9093,2@192.168.0.228:9093,3@192.168.0.89:9093

# ===== 网络监听配置 =====

# listeners --- Broker 监听地址列表
# 格式: {协议}://{主机}:{端口}
# 0.0.0.0 表示绑定所有网络接口
listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093

# advertised.listeners --- 对外公布的访问地址
# 客户端通过此地址连接 Broker
# 必须使用客户端可访问的 IP/域名
# 如果 Broker 在 NAT/云环境,此处应为公网 IP
advertised.listeners=PLAINTEXT://119.3.218.94:9092

# inter.broker.listener.name --- Broker 间通信使用的 listener
# 对应 listeners 中的协议名(不是端口)
inter.broker.listener.name=PLAINTEXT

# controller.listener.names --- Controller 通信使用的 listener 列表
# 逗号分隔的协议名列表
controller.listener.names=CONTROLLER

# listener.security.protocol.map --- 协议名到安全协议的映射
# 格式: {协议名}:{安全协议},{协议名}:{安全协议},...
# 安全协议: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT

# ===== 日志存储配置 =====

# log.dirs --- 数据存储目录
# 可配置多个目录(逗号分隔),Kafka 会将分区均匀分布
# 推荐使用独立磁盘/SSD
log.dirs=/opt/kafka/data

# num.partitions --- 新建 Topic 默认分区数
# 生产环境建议根据吞吐需求设置,通常 6~12
num.partitions=8

# default.replication.factor --- 默认副本因子
# 必须 ≤ Broker 数量,生产环境建议 3
default.replication.factor=3

# min.insync.replicas --- 最小同步副本数
# 配合 acks=all 使用,保证数据可靠性
# 通常设置为 replication.factor - 1
min.insync.replicas=2

# ===== 日志保留策略 =====

# log.retention.hours --- 消息保留时间(小时)
# 超过此时间的消息将被删除(delete 策略)或压缩(compact 策略)
# 默认 168 小时 = 7 天
log.retention.hours=168

# log.segment.bytes --- 单个日志段文件最大大小
# 到达此大小后,创建新的日志段
# 默认 1 GB = 1073741824
log.segment.bytes=1073741824

# log.retention.check.interval.ms --- 日志清理检查间隔
# 默认 300000 ms = 5 分钟
log.retention.check.interval.ms=300000

# ===== 网络线程配置 =====

# num.network.threads --- 网络线程数
# 处理网络请求的线程数,生产环境建议 CPU 核数
num.network.threads=3

# num.io.threads --- IO 线程数
# 处理磁盘 IO 的线程数,建议 CPU 核数 * 2
num.io.threads=8

# socket.send.buffer.bytes --- Socket 发送缓冲区大小
socket.send.buffer.bytes=102400

# socket.receive.buffer.bytes --- Socket 接收缓冲区大小
socket.receive.buffer.bytes=102400

# socket.request.max.bytes --- Socket 请求最大字节数
# 默认 100 MB = 104857600
socket.request.max.bytes=104857600

# ===== 内部 Topic 配置 =====

# offsets.topic.replication.factor --- __consumer_offsets 副本因子
# 建议与 default.replication.factor 一致
offsets.topic.replication.factor=3

# transaction.state.log.replication.factor --- 事务日志副本因子
transaction.state.log.replication.factor=3

# transaction.state.log.min.isr --- 事务日志最小 ISR
transaction.state.log.min.isr=2

# ===== 消费者组配置 =====

# group.initial.rebalance.delay.ms --- 初始重平衡延迟
# 设为 0 可加快首次消费启动
group.initial.rebalance.delay.ms=0

# ===== 压缩配置 =====

# compression.type --- 消息压缩算法
# producer: 保留生产者设置的压缩格式(推荐)
# 可选:none, gzip, snappy, lz4, zstd
compression.type=producer
2.2.3 KRaft 存储格式化
bash 复制代码
# 1. 生成集群唯一 ID(仅在一个节点执行)
/opt/kafka/bin/kafka-storage.sh random-uuid
# 输出: 1S9ggrMYQaCHBqfZy8hhOg

# 2. 格式化所有节点(每个节点都要执行)
mkdir -p /opt/kafka/data
/opt/kafka/bin/kafka-storage.sh format \
  -t 1S9ggrMYQaCHBqfZy8hhOg \
  -c /opt/kafka/config/server.properties \
  --ignore-formatted

# 输出:
# Bootstrap metadata: BootstrapMetadata(
#   metadataVersionLevel=30, source=format command
# )
# Formatting metadata directory /opt/kafka/data with metadata.version 4.3-IV0.

# 注意:所有节点必须使用相同的 UUID!
# Broker-only 节点 (process.roles=broker) 也需要格式化
2.2.4 启动与验证
bash 复制代码
# 启动 Kafka(后台守护模式)
nohup /opt/kafka/bin/kafka-server-start.sh \
  /opt/kafka/config/server.properties \
  > /opt/kafka/kafka.log 2>&1 &

# 检查进程
ps aux | grep kafka.Kafka
# root  18712  64.2  6.9  3746476 241472 ?  Sl  12:03  0:03 java ...

# 查看集群状态(KRaft Metadata Quorum)
/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server 192.168.0.54:9092 \
  describe --status

# 输出:
# ClusterId:              1S9ggrMYQaCHBqfZy8hhOg
# LeaderId:               1
# LeaderEpoch:            1
# HighWatermark:          192
# MaxFollowerLag:         0             ← 所有节点完全同步
# MaxFollowerLagTimeMs:   0
# CurrentVoters:          [1, 2, 3]
# CurrentObservers:       [4]
2.2.5 创建 Topic 验证
bash 复制代码
# 创建 Topic
kafka-topics.sh --bootstrap-server 192.168.0.54:9092 \
  --create --topic test-basic \
  --partitions 4 --replication-factor 3

# 查看 Topic 详情
kafka-topics.sh --bootstrap-server 192.168.0.54:9092 \
  --describe --topic test-basic

实战输出:

复制代码
Topic: test-basic  PartitionCount: 4  ReplicationFactor: 3

Partition 0: Leader=3  Replicas=3,4,1  Isr=3,4,1
Partition 1: Leader=4  Replicas=4,1,2  Isr=4,1,2
Partition 2: Leader=1  Replicas=1,2,3  Isr=1,2,3
Partition 3: Leader=2  Replicas=2,3,4  Isr=2,3,4

关键观察:

  • 4 个分区的 Leader 分布在 4 个 Broker(3, 4, 1, 2)→ 负载均衡 ✓
  • 所有分区的 ISR = Replicas → 副本完全同步 ✓
  • Replication Factor = 3,每个分区有 3 个副本 ✓

第三章:Kafka 核心 API 详解

3.1 Producer API

3.1.1 Producer 配置参数详解
java 复制代码
Properties props = new Properties();

// bootstrap.servers --- Broker 地址列表
// 生产者用此列表发现集群所有 Broker
// 只需提供部分节点,客户端会自动发现全部
// 建议提供 2-3 个节点以防单点故障
props.put("bootstrap.servers", "192.168.0.54:9092,192.168.0.228:9092");

// key.serializer --- Key 序列化器
// 必须实现 org.apache.kafka.common.serialization.Serializer
// 常用:StringSerializer, IntegerSerializer, BytesSerializer
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");

// value.serializer --- Value 序列化器
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

// acks --- 确认机制
// 0: 不等待确认,最快但可能丢消息
// 1: 等待 Leader 确认,默认值
// all (-1): 等待所有 ISR 确认,最安全
props.put("acks", "all");

// retries --- 重试次数(Kafka 3.x+ 默认 Integer.MAX_VALUE)
props.put("retries", 3);

// batch.size --- 批量发送大小(字节)
// 多条消息打包成一个请求发送
// 默认 16384 (16KB)
props.put("batch.size", 16384);

// linger.ms --- 批量等待时间(毫秒)
// 延迟发送以等待更多消息凑批
// 默认 0(立即发送)
// 设为 5-10ms 可在吞吐和延迟间取得平衡
props.put("linger.ms", 5);

// buffer.memory --- 生产者总缓冲区大小
// 默认 33554432 (32MB)
props.put("buffer.memory", 33554432);

// compression.type --- 压缩算法
// none: 不压缩
// gzip: 高压缩率,CPU 开销大
// snappy: 平衡压缩率和速度
// lz4: 快速压缩,推荐
// zstd: 最高压缩率
props.put("compression.type", "lz4");

// max.request.size --- 单次请求最大大小(默认 1MB)
props.put("max.request.size", 1048576);
3.1.2 发送消息方式
java 复制代码
import org.apache.kafka.clients.producer.*;

// === 方式 1: 发后即忘 (Fire-and-Forget) ===
producer.send(new ProducerRecord<>("topic", "key", "value"));
// 不关心结果,可能丢失消息

// === 方式 2: 同步发送 (Sync) ===
try {
    RecordMetadata meta = producer.send(
        new ProducerRecord<>("topic", "key", "value")
    ).get();  // 阻塞等待结果
    System.out.printf("offset=%d, partition=%d%n", 
        meta.offset(), meta.partition());
} catch (Exception e) {
    e.printStackTrace();
}

// === 方式 3: 异步发送 (Async with Callback) ===
producer.send(new ProducerRecord<>("topic", "key", "value"),
    new Callback() {
        @Override
        public void onCompletion(RecordMetadata meta, Exception e) {
            if (e != null) {
                // 发送失败
                System.err.println("Send failed: " + e.getMessage());
            } else {
                // 发送成功
                System.out.printf("Sent to partition=%d offset=%d%n",
                    meta.partition(), meta.offset());
            }
        }
    }
);
3.1.3 Python 客户端示例
python 复制代码
from kafka import KafkaProducer
import json

# === 基础生产者 ===
producer = KafkaProducer(
    bootstrap_servers=['192.168.0.54:9092', '192.168.0.228:9092'],
    value_serializer=lambda v: json.dumps(v).encode(),
    key_serializer=lambda k: k.encode() if k else None,
    acks='all'  # 等待所有副本确认
)

# 发送消息
future = producer.send(
    'test-basic',
    key='user-0',
    value={'user': 'user-0', 'msg_id': 0, 'data': 'python-test'}
)

# 获取发送结果(同步等待)
metadata = future.get(timeout=10)
print(f'Partition: {metadata.partition}, Offset: {metadata.offset}')

producer.flush()
producer.close()

实战输出:

复制代码
Sent: key=user-0 -> partition=3, offset=0
Sent: key=user-1 -> partition=0, offset=10
Sent: key=user-2 -> partition=0, offset=11
Sent: key=user-0 -> partition=3, offset=1    ← 相同 Key 返回同一分区
Sent: key=user-1 -> partition=0, offset=12
Sent: key=user-2 -> partition=0, offset=13
Sent: key=user-0 -> partition=3, offset=2
Sent: key=user-1 -> partition=0, offset=14
Sent: key=user-2 -> partition=0, offset=15
Sent: key=user-0 -> partition=3, offset=3
3.1.4 幂等性配置(Idempotence)
properties 复制代码
# 幂等性生产者 --- 保证 exactly-once 语义(单分区)
# 开启后自动设置: acks=all, retries=MAX, max.in.flight.requests.per.connection≤5
enable.idempotence=true

# 原理:每个生产者分配 PID (Producer ID),每条消息带 Sequence Number
# Broker 根据 <PID, Partition, SeqNum> 去重
3.1.5 事务支持(Transaction)
java 复制代码
// 1. 配置事务 ID
props.put("transactional.id", "my-transactional-id");

// 2. 初始化事务
producer.initTransactions();

// 3. 开始事务
producer.beginTransaction();
try {
    producer.send(new ProducerRecord<>("topic-a", "key", "value"));
    producer.send(new ProducerRecord<>("topic-b", "key", "value"));
    // 4. 提交事务
    producer.commitTransaction();
} catch (Exception e) {
    // 5. 回滚事务
    producer.abortTransaction();
}
3.1.6 自定义分区器(Partitioner)
java 复制代码
public class CustomPartitioner implements Partitioner {
    @Override
    public int partition(String topic, Object key, byte[] keyBytes,
                        Object value, byte[] valueBytes, Cluster cluster) {
        // 自定义分区逻辑
        // 例如:特定 Key 固定发往 Partition 0
        if ("VIP".equals(key)) {
            return 0;
        }
        // 其他 Key 使用默认哈希
        return Math.abs(key.hashCode()) % cluster.partitionCountForTopic(topic);
    }

    @Override
    public void close() {}

    @Override
    public void configure(Map<String, ?> configs) {}
}

// 使用自定义分区器
props.put("partitioner.class", "com.example.CustomPartitioner");

3.2 Consumer API

3.2.1 Consumer 配置参数详解
java 复制代码
Properties props = new Properties();
props.put("bootstrap.servers", "192.168.0.54:9092");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

// group.id --- 消费者组 ID
// 同一个 Group 的消费者共享分区分配
props.put("group.id", "my-consumer-group");

// auto.offset.reset --- 无初始 Offset 时的策略
// earliest: 从最早的消息开始(相当于 --from-beginning)
// latest: 从最新的消息开始(默认,只消费新消息)
// none: 没有 offset 时抛异常
props.put("auto.offset.reset", "earliest");

// enable.auto.commit --- 是否自动提交 Offset
// true: 自动提交(默认),简单但可能重复消费
// false: 手动提交,精确控制
props.put("enable.auto.commit", "false");

// auto.commit.interval.ms --- 自动提交间隔(默认 5000ms)
props.put("auto.commit.interval.ms", "5000");

// max.poll.records --- 单次 poll() 最大返回记录数
// 默认 500,根据消息处理速度调整
props.put("max.poll.records", "500");

// max.poll.interval.ms --- 两次 poll() 最大间隔
// 超过此时间消费者被认为"失联",触发重平衡
// 默认 300000 (5分钟)
props.put("max.poll.interval.ms", "300000");

// session.timeout.ms --- 会话超时
// 消费者在此时间内未发送心跳,被认为已下线
// 默认 45000 (45秒)
props.put("session.timeout.ms", "45000");

// heartbeat.interval.ms --- 心跳间隔
// 应小于 session.timeout.ms 的 1/3
// 默认 3000 (3秒)
props.put("heartbeat.interval.ms", "3000");

// fetch.min.bytes --- 最小拉取字节数
// Broker 等待积累到此字节数再返回(可减少请求次数)
props.put("fetch.min.bytes", "1");

// fetch.max.wait.ms --- 最大等待时间
// 配合 fetch.min.bytes,到达时间即使不足也会返回
props.put("fetch.max.wait.ms", "500");
3.2.2 消费消息示例
java 复制代码
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);

// 订阅方式 1: subscribe --- 自动分区分配(推荐)
consumer.subscribe(Arrays.asList("topic-a", "topic-b"));

// 订阅方式 2: assign --- 手动指定分区
TopicPartition partition0 = new TopicPartition("topic-a", 0);
consumer.assign(Arrays.asList(partition0));

// 消息拉取循环
try {
    while (true) {
        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
        for (ConsumerRecord<String, String> record : records) {
            System.out.printf("topic=%s, partition=%d, offset=%d, key=%s, value=%s%n",
                record.topic(), record.partition(), 
                record.offset(), record.key(), record.value());
        }
        // 手动提交 Offset
        consumer.commitSync();
    }
} finally {
    consumer.close();
}
3.2.3 Python 消费者示例
python 复制代码
from kafka import KafkaConsumer
import json

consumer = KafkaConsumer(
    'test-basic',
    bootstrap_servers='192.168.0.54:9092',
    auto_offset_reset='earliest',     # 从最早消息开始
    enable_auto_commit=False,          # 手动提交
    group_id='python-test-group',
    value_deserializer=lambda v: json.loads(v.decode()),
    key_deserializer=lambda k: k.decode() if k else None,
    max_poll_records=5
)

for msg in consumer:
    print(f'partition={msg.partition} offset={msg.offset} '
          f'key={msg.key} value={msg.value}')
3.2.4 Offset 管理
java 复制代码
// === 自动提交 (默认) ===
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "5000");  // 5秒提交一次
// 优点:简单;缺点:可能重复消费

// === 手动同步提交 ===
consumer.commitSync();
// 阻塞直到提交完成,保证提交成功,但影响吞吐

// === 手动异步提交 ===
consumer.commitAsync(new OffsetCommitCallback() {
    @Override
    public void onComplete(Map<TopicPartition, OffsetAndMetadata> offsets, 
                          Exception e) {
        if (e != null) {
            System.err.println("Commit failed: " + e.getMessage());
        }
    }
});
// 不阻塞,吞吐高,但可能提交失败

// === 提交特定 Offset ===
Map<TopicPartition, OffsetAndMetadata> offsets = new HashMap<>();
offsets.put(new TopicPartition("topic", 0), 
           new OffsetAndMetadata(12345L));
consumer.commitSync(offsets);

3.3 Admin API

java 复制代码
import org.apache.kafka.clients.admin.*;

Properties props = new Properties();
props.put("bootstrap.servers", "192.168.0.54:9092");
AdminClient admin = AdminClient.create(props);

// 创建 Topic
NewTopic newTopic = new NewTopic("my-topic", 4, (short) 3);
admin.createTopics(Arrays.asList(newTopic)).all().get();

// 列出 Topic
ListTopicsResult topics = admin.listTopics();
topics.listings().get().forEach(t -> System.out.println(t.name()));

// 描述 Topic
DescribeTopicsResult desc = admin.describeTopics(Arrays.asList("test-basic"));
desc.all().get().forEach((name, info) -> {
    System.out.printf("Topic: %s, Partitions: %d, RF: %d%n",
        name, info.partitions().size(), 
        info.partitions().get(0).replicas().size());
});

// 增加分区
admin.createPartitions(
    Map.of("my-topic", NewPartitions.increaseTo(8))
).all().get();

// 删除 Topic
admin.deleteTopics(Arrays.asList("old-topic")).all().get();

admin.close();

3.4 Streams API

Kafka Streams 是用于构建流处理应用的 Java 库:

复制代码
Kafka Streams 架构:

  Source Topic ──► [Stream Processor] ──► [State Store]
                        │
                        ├── map / filter / flatMap
                        ├── join / leftJoin
                        ├── aggregate / reduce
                        └── window (Tumbling/Hopping/Session)
                                          │
                                          ▼
                                    Sink Topic
java 复制代码
// Kafka Streams 示例:单词计数
StreamsBuilder builder = new StreamsBuilder();
KStream<String, String> source = builder.stream("input-topic");

KTable<String, Long> counts = source
    .flatMapValues(text -> Arrays.asList(text.toLowerCase().split(" ")))
    .groupBy((key, word) -> word)
    .count();

counts.toStream().to("output-topic");

KafkaStreams streams = new KafkaStreams(builder.build(), config);
streams.start();

第四章:Kafka 核心机制深入

4.1 存储机制

4.1.1 日志存储结构(Log Segment)
复制代码
Kafka 日志存储目录结构:

/opt/kafka/data/test-basic-0/
├── 00000000000000000000.log          ← 消息数据文件
├── 00000000000000000000.index        ← 偏移量索引
├── 00000000000000000000.timeindex    ← 时间戳索引
├── leader-epoch-checkpoint           ← Leader Epoch 检查点
└── partition.metadata                ← 分区元数据

每个 Partition 对应一个目录,内部由多个 Log Segment 组成:

  [Log Segment 0]   [Log Segment 1]   [Log Segment 2]   [Active Segment]
  .log: 0 ~ 999     .log: 1000~1999   .log: 2000~2999   .log: 3000~...
  .index            .index            .index            (正在写入)
  .timeindex        .timeindex        .timeindex

Segment 文件命名规则:以该 Segment 第一条消息的 Offset 为基准(20位数字,左补0)

实战验证:

复制代码
# 查看实际存储结构
ls -la /opt/kafka/data/test-basic-0/
-rw-r--r--  00000000000000000000.index      10485760  ← 10MB 索引文件
-rw-r--r--  00000000000000000000.log            366  ← 实际消息数据
-rw-r--r--  00000000000000000000.timeindex  10485756  ← 10MB 时间索引
-rw-r--r--  leader-epoch-checkpoint                8
-rw-r--r--  partition.metadata                     43
4.1.2 索引文件

偏移量索引 (Offset Index):

复制代码
作用:根据 Offset 快速定位消息在 .log 文件中的物理位置

索引结构 (稀疏索引,不是每条消息都有):
  ┌──────────────────────────────────────┐
  │ Relative Offset │ Physical Position  │
  ├──────────────────┼───────────────────┤
  │        0        │        0          │
  │      100        │     8192          │
  │      200        │    16384          │
  │      ...        │      ...          │
  └──────────────────┴───────────────────┘

查找 Offset=150 的流程:
  1. 二分查找索引 → 定位到 Relative Offset=100, Position=8192
  2. 从 .log 文件 Position=8192 开始顺序扫描
  3. 找到 Offset=150 的消息

时间戳索引 (Time Index):

复制代码
作用:根据时间戳快速定位 Offset

索引结构:
  ┌──────────────────────────────────────┐
  │ Timestamp (ms)    │ Relative Offset  │
  ├────────────────────┼─────────────────┤
  │  1717228800000    │       0         │
  │  1717228801000    │     100         │
  │  ...              │     ...         │
  └────────────────────┴─────────────────┘
4.1.3 零拷贝技术(Zero Copy)
复制代码
传统文件传输(4次拷贝,4次上下文切换):

  Disk → Read Buffer → User Buffer → Socket Buffer → NIC
   ↑         ↑              ↑              ↑          ↑
   1         2拷贝           3拷贝          4拷贝

Kafka 零拷贝 (sendfile 系统调用,2次拷贝,2次上下文切换):

  Disk → Read Buffer → Socket Buffer → NIC
   ↑         ↑              ↑          ↑
   1          (DMA)         (DMA)      

  节省 CPU 拷贝,大幅提升吞吐量 ⚡
4.1.4 页缓存(Page Cache)优化
复制代码
Kafka 重度依赖操作系统的 Page Cache:

写路径:
  Producer → Kafka 进程 → OS Page Cache → 磁盘 (异步刷盘)
                          ↑
                    写入即返回,不等待磁盘

读路径:
  Consumer → Kafka 进程 → OS Page Cache (命中) → 零拷贝发送
                          ↑
                    热点数据在内存中,无磁盘 IO

优化效果:
  - Kafka 不自己管理缓存,交由 OS
  - 数据写入 Page Cache 即返回确认
  - 消费者读取时大概率命中 Page Cache
  - 剩余可用内存全部用作 Page Cache
4.1.5 文件刷盘策略
properties 复制代码
# Kafka 依赖 OS 后台刷盘,不强制同步写入

# log.flush.interval.messages --- 多少条消息刷盘一次
# 默认 Long.MAX_VALUE(不按消息条数刷盘)
log.flush.interval.messages=10000

# log.flush.interval.ms --- 刷盘间隔(毫秒)
# 默认 Long.MAX_VALUE(不按时间刷盘)
log.flush.interval.ms=1000

# ⚠️ 建议:使用默认值,依赖 OS 后台刷盘 + 副本机制保证可靠性
# 强制刷新会严重影响性能!

4.2 分区与副本机制

4.2.1 分区策略与优势
复制代码
分区 (Partition) 是 Kafka 存储和并行处理的基本单元:

优势 1 --- 水平扩展:
  Topic 数据分散在多个 Broker 上,突破单机磁盘限制

优势 2 --- 并行处理:
  多个消费者并行消费不同分区,提升吞吐量

优势 3 --- 负载均衡:
  Leader 分布在多台 Broker,避免单点热点

分区数量选择指南:
  ┌─────────────┬──────────────┐
  │  场景        │  建议分区数  │
  ├─────────────┼──────────────┤
  │  低吞吐 Topic │  3-6        │
  │  中吞吐 Topic │  6-12       │
  │  高吞吐 Topic │  12-24      │
  │  极高吞吐     │  24-100+    │
  └─────────────┴──────────────┘

⚠️ 注意:分区数越多,Leader 选举和文件句柄开销越大
4.2.2 副本机制(Leader、Follower)
复制代码
┌──────────────────────────────────────────────────────────┐
│                  Partition 0, RF=3                       │
│                                                          │
│  ┌─────────────────┐                                     │
│  │   Broker 3      │  ← Leader                          │
│  │   (处理所有读写)  │                                     │
│  └────────┬────────┘                                     │
│           │ 数据复制 (Fetch Request)                      │
│     ┌─────┴─────┐                                        │
│     ▼           ▼                                        │
│  ┌────────┐  ┌────────┐                                  │
│  │Broker 4│  │Broker 1│  ← Followers (只从 Leader 同步)  │
│  └────────┘  └────────┘                                  │
│                                                          │
│  ISR = [3, 4, 1]  ← 所有在同步的副本                      │
│                                                          │
│  如果 Broker 3 故障:                                     │
│    → Controller 从 ISR 中选举新 Leader (4 或 1)           │
│    → 新 Leader 接管读写                                   │
│    → 客户端自动重连                                       │
└──────────────────────────────────────────────────────────┘
4.2.3 ISR(In-Sync Replicas)机制
复制代码
ISR 是与 Leader 保持同步的副本集合。

加入 ISR 条件:
  - Follower 在 replica.lag.time.max.ms (默认 30s) 内向 Leader 发送 Fetch 请求
  - Follower 的 LEO 与 Leader 的 LEO 差距在可接受范围

移出 ISR 条件:
  - 超过 replica.lag.time.max.ms 未发送 Fetch 请求
  - LEO 落后太多(由 replica.lag.max.messages 控制,4.x 已弃用)

实战 ISR 状态:
  Topic: test-basic  Partition: 0  Leader: 3  Isr: 3,4,1  ✓ 全部同步
  Topic: test-basic  Partition: 1  Leader: 4  Isr: 4,1,2  ✓ 全部同步
  Topic: test-basic  Partition: 2  Leader: 1  Isr: 1,2,3  ✓ 全部同步
  Topic: test-basic  Partition: 3  Leader: 2  Isr: 2,3,4  ✓ 全部同步
4.2.4 HW(High Watermark)与 LEO(Log End Offset)
复制代码
HW 和 LEO 是 Kafka 副本机制的核心概念:

  LEO (Log End Offset) --- 副本下一条待写入消息的 Offset
  HW  (High Watermark)  --- 消费者可见的最高 Offset(所有 ISR 都已确认)

  ┌─────────────────────────────────────────────┐
  │              Partition 日志                   │
  │                                             │
  │  消息: [0] [1] [2] [3] [4] [5] [6] [7] ...  │
  │         │              │    │          │     │
  │         │  已提交       │    │ 未提交    │     │
  │         │  (消费者可见)  │    │ (消费者不可见) │
  │         │              │    │          │     │
  │  Offset: 0             HW=4  LEO=8           │
  │                                             │
  │  Leader:   LEO=8, HW=4                       │
  │  Follower: LEO=6, HW=4  ← 正在同步 5,6       │
  │                                             │
  │  当 Follower 同步到 5,6 后:                   │
  │  Leader 推进 HW → 6                          │
  └─────────────────────────────────────────────┘

HW 的作用:
  1. 消费可见性控制 --- 只有 HW 之前的消息才对消费者可见
  2. 故障恢复 --- 新 Leader 从 HW 开始,避免数据不一致
  3. 配合 min.insync.replicas 保证消息不丢失
4.2.5 副本同步流程
复制代码
Producer 写入 + 副本同步完整流程 (acks=all, min.insync.replicas=2):

  Producer                Leader (3)              Follower (4)       Follower (1)
     │                       │                       │                 │
     │ 1. Produce Request    │                       │                 │
     │──────────────────────►│                       │                 │
     │                       │ 2. Append to Log      │                 │
     │                       │    LEO: 7→8           │                 │
     │                       │                       │                 │
     │                       │ 3. Follower Fetch     │                 │
     │                       │◄──────────────────────│ (拉取模式)       │
     │                       │◄────────────────────────────────────────│
     │                       │                       │                 │
     │                       │ 4. Return Records     │                 │
     │                       │──────────────────────►│ LEO: 5→8        │
     │                       │────────────────────────────────────────►│ LEO: 5→8
     │                       │                       │                 │
     │                       │ 5. HW 推进: 6→8       │                 │
     │                       │ (所有 ISR LEO≥8)      │                 │
     │                       │                       │                 │
     │ 6. ACK (offset=8)    │                       │                 │
     │◄──────────────────────│                       │                 │
     │                       │                       │                 │

关键点:
  - Follower 使用拉取模式(Fetch Request),不是 Leader 推送
  - HW 在所有 ISR 副本同步后统一推进
  - min.insync.replicas=2 意味着 Leader + 至少 1 个 Follower 确认即可

4.3 消费者组与重平衡

4.3.1 消费者组概念
复制代码
┌─────────────────────────────────────────────────────────────┐
│                  Consumer Group 示例                         │
│                                                             │
│  Group: "order-processor" (3 Consumer)                      │
│                                                             │
│  Topic: orders (4 Partitions)                               │
│                                                             │
│  Consumer A ── Partition 0, Partition 1                     │
│  Consumer B ── Partition 2                                  │
│  Consumer C ── Partition 3                                  │
│                                                             │
│  规则:                                                      │
│  1. 同一 Group 内,每个 Partition 只能被一个 Consumer 消费    │
│  2. 一个 Consumer 可以消费多个 Partition                     │
│  3. Consumer 数量 ≤ Partition 数量(超出则空闲)              │
│  4. 不同 Group 之间完全隔离                                  │
└─────────────────────────────────────────────────────────────┘
4.3.2 分区分配策略
复制代码
Range (默认):
  按 Topic 分区编号范围分配给消费者
  例: 8 分区, 3 消费者 → A(0-2), B(3-5), C(6-7)
  问题:可能导致分配不均

RoundRobin:
  轮询分配,更均衡
  例: A(0,3,6), B(1,4,7), C(2,5)
  注意: 需要所有消费者订阅相同 Topic

Sticky (合作式,推荐):
  基于 RoundRobin,但尽可能保持原有分配
  重平衡时只移动必要的分区,减少暂停时间
  配置: partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor
4.3.3 重平衡触发条件
复制代码
重平衡 (Rebalance) 触发条件:

1. 新消费者加入 Consumer Group
2. 已有消费者离开(心跳超时 / 主动离开)
3. Topic 分区数变化(增加分区)
4. 消费者处理时间超过 max.poll.interval.ms
5. Consumer Group 订阅的 Topic 被创建/删除

重平衡过程:
  ┌──────────────────────────────────────────────────────┐
  │ 1. Group Coordinator 检测到消费者变更                 │
  │ 2. 通知所有消费者重新加入 Group (JoinGroup)            │
  │ 3. 选举 Group Leader (第一个加入的消费者)              │
  │ 4. Leader 执行分区分配方案 (PartitionAssignor)         │
  │ 5. Leader 将分配结果发送给 Coordinator (SyncGroup)     │
  │ 6. Coordinator 将分配结果下发给各消费者                │
  │ 7. 消费者收到新分配,继续消费                          │
  │                                                      │
  │ ⚠️ 重平衡期间整个 Group 暂停消费!(STW)                │
  │ ⚠️ 合作式协议 (CooperativeStickyAssignor) 可减少暂停   │
  └──────────────────────────────────────────────────────┘
4.3.4 避免频繁重平衡策略
properties 复制代码
# 1. 增大 session.timeout.ms
# 防止网络抖动导致的短暂"失联"
session.timeout.ms=60000  # 默认 45s

# 2. 增大 max.poll.interval.ms
# 防止消息处理时间过长被踢出 Group
max.poll.interval.ms=600000  # 默认 5min,生产可设 10min+

# 3. 控制 max.poll.records
# 防止一次拉取过多消息导致处理超时
max.poll.records=200  # 默认 500

# 4. 使用合作式分配策略
partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor

# 5. group.initial.rebalance.delay.ms
# 控制首次重平衡延迟,避免频繁启动时的重平衡
group.initial.rebalance.delay.ms=3000  # 默认 0

4.4 控制器(Controller)

4.4.1 Controller 选举机制
复制代码
在 KRaft 模式下,Controller 由 Raft 协议选举产生:

┌─────────────────────────────────────────────────────────┐
│                   Controller 选举                         │
│                                                         │
│  Quorum: [Node 1, Node 2, Node 3]                       │
│                                                         │
│  启动时:所有节点发起 Raft Leader 选举                     │
│  ┌──────────────────────────────────────────────┐       │
│  │ Node 1: 发起投票 (Term=1)                     │       │
│  │ Node 2: 投票给 Node 1                        │       │
│  │ Node 3: 投票给 Node 1                        │       │
│  │ → Node 1 获得多数票,成为 Active Controller   │       │
│  └──────────────────────────────────────────────┘       │
│                                                         │
│  实战状态:                                              │
│    LeaderId:       1  ← Node 1 是 Active Controller    │
│    LeaderEpoch:    1                                    │
│    CurrentVoters:  [1, 2, 3]                            │
│    CurrentObservers: [4]                                │
└─────────────────────────────────────────────────────────┘
4.4.2 Controller 职责
复制代码
Active Controller 的核心职责:

1. 分区管理
   - 创建/删除 Topic
   - 增加分区
   - 分区副本分配

2. Leader 选举
   - 监控 Broker 故障
   - 从 ISR 中选举新 Leader
   - 通知所有 Broker 新的 Leader 信息

3. 集群管理
   - Broker 加入/离开处理
   - 维护集群元数据

4. 再平衡
   - 副本迁移(kafka-reassign-partitions.sh)
   - Preferred Leader 选举
4.4.3 Controller 故障转移
复制代码
Controller 故障转移流程:

1. Follower 检测到 Leader 心跳超时
2. Follower 发起新一轮选举(LeaderEpoch++)
3. 获得多数票的节点成为新 Active Controller
4. 新 Controller 读取 Metadata Topic 恢复状态
5. 新 Controller 接管所有管理职责

故障转移时间:通常 < 3 秒(取决于配置的超时时间)

第五章:Kafka 生产者详解

5.1 消息发送流程

复制代码
Producer 内部发送流程:

┌──────────────────────────────────────────────────────────────┐
│                     Producer 发送流程                          │
│                                                              │
│  1. send(record)                                             │
│     │                                                        │
│     ▼                                                        │
│  2. Serializer (Key + Value 序列化)                           │
│     │                                                        │
│     ▼                                                        │
│  3. Partitioner (选择目标分区)                                 │
│     │  - Key 存在 → hash(key) % num_partitions              │
│     │  - Key 为 null → Round-Robin / Sticky                  │
│     │                                                        │
│     ▼                                                        │
│  4. RecordAccumulator (消息缓冲区)                             │
│     │  - 按 <Topic, Partition> 分组                          │
│     │  - 每个分区一个 Batch (Deque)                           │
│     │  - batch.size 控制 Batch 大小                          │
│     │  - buffer.memory 控制总缓冲区                           │
│     │                                                        │
│     ▼                                                        │
│  5. Sender Thread (发送线程)                                  │
│     │  - 检查 Batch 是否就绪 (full / linger.ms)              │
│     │  - 构建 ProduceRequest                                  │
│     │  - 发送到 Broker Leader                                  │
│     │                                                        │
│     ▼                                                        │
│  6. Broker 处理                                               │
│     │  - 写入 Leader 日志                                     │
│     │  - 副本同步(异步)                                      │
│     │  - 返回 ProduceResponse (根据 acks)                     │
│     │                                                        │
│     ▼                                                        │
│  7. Callback (如果配置) / Future.get()                        │
│     - Retry (如果失败且可重试)                                 │
│     - 返回 RecordMetadata (partition, offset, timestamp)     │
└──────────────────────────────────────────────────────────────┘

5.2 关键参数配置

5.2.1 acks 参数详解
复制代码
acks=0:
  Producer 发送后不等待任何确认
  → 最快,但消息可能丢失(网络问题/Broker 故障)
  → 适合:指标收集、日志(容忍少量丢失)

acks=1 (默认):
  Producer 等待 Leader 确认写入
  → 平衡性能和可靠性
  → 如果 Leader 写入后、Follower 同步前故障 → 消息丢失
  → 适合:大多数业务场景

acks=all (-1):
  Producer 等待所有 ISR 确认写入
  → 最可靠,配合 min.insync.replicas 使用
  → 如果 ISR 数量 < min.insync.replicas → 写入失败
  → 适合:金融/交易等不能丢消息的场景

性能对比(实测,2vCPU/4GiB,跨公网):
  acks=0:    ~20,000 msg/s
  acks=1:    ~13,675 msg/s  (本次实测)
  acks=all:  ~5,000 msg/s   (估算)
5.2.2 重试机制
properties 复制代码
# retries --- 重试次数
# 3.x+ 默认 Integer.MAX_VALUE(无限重试)
# 生产环境建议设置有限次数
retries=3

# retry.backoff.ms --- 重试间隔(毫秒)
retry.backoff.ms=100

# delivery.timeout.ms --- 投递超时(包含重试)
# 默认 120000 (2分钟)
delivery.timeout.ms=120000

# 重试可能导致消息乱序 → 设置 max.in.flight.requests.per.connection=1
max.in.flight.requests.per.connection=5  # 默认,≤5 时配合幂等性可保证顺序
5.2.3 批处理优化
properties 复制代码
# batch.size --- 批次大小(字节)
# 默认 16384 (16KB),可设大一些提升吞吐
batch.size=32768  # 32KB

# linger.ms --- 延迟发送(毫秒)
# 设为 0 立即发送(低延迟,低吞吐)
# 设为 5-10ms 等待更多消息凑批(高吞吐,略高延迟)
linger.ms=5

# buffer.memory --- 生产者总缓冲区(字节)
# 默认 33554432 (32MB)
# 如果生产速度 > 发送速度,缓冲区满后会阻塞 send()
buffer.memory=67108864  # 64MB

# 调优黄金法则:
# 高吞吐场景 → 增大 batch.size, linger.ms
# 低延迟场景 → 减小 batch.size, linger.ms=0
5.2.4 压缩配置
复制代码
压缩算法对比:

┌──────────┬──────────┬──────────┬──────────┐
│  算法     │ 压缩率   │ CPU 开销 │ 适用场景  │
├──────────┼──────────┼──────────┼──────────┤
│  none    │  1x      │  无      │ 不压缩    │
│  gzip    │  最高    │  最高    │ 带宽有限  │
│  snappy  │  中等    │  低      │ 平衡选择  │
│  lz4     │  中等    │  最低    │ 推荐首选  │
│  zstd    │  高      │  中等    │ 新项目    │
└──────────┴──────────┴──────────┴──────────┘

推荐:compression.type=producer(保留生产者原始压缩)

5.3 可靠性保证

5.3.1 消息不丢失配置(Producer 端)
properties 复制代码
# 消息不丢失的完整 Producer 配置
acks=all                                    # 所有 ISR 确认
enable.idempotence=true                     # 幂等性
max.in.flight.requests.per.connection=5     # 配合幂等性保证顺序
retries=2147483647                          # 无限重试(默认值)
compression.type=lz4                        # 压缩
5.3.2 消息不丢失配置(Broker 端)
properties 复制代码
# Broker 端:可靠性配置
default.replication.factor=3                # 3 副本
min.insync.replicas=2                       # 最少 2 个 ISR 确认
offsets.topic.replication.factor=3          # Offset Topic 3 副本
transaction.state.log.replication.factor=3  # 事务日志 3 副本
transaction.state.log.min.isr=2

# 禁用 Unclean Leader 选举(数据一致性优先)
unclean.leader.election.enable=false
5.3.3 消息顺序性保证
复制代码
Kafka 消息顺序性:

✓ 分区内有序 --- 同一分区内消息按 Offset 严格有序
✗ 跨分区无序 --- 不同分区之间无顺序保证
✗ 重试可能乱序 --- 除非 max.in.flight.requests.per.connection=1

全局有序方案:
  1. 单分区 Topic → 全局有序,但吞吐受限
  2. Key 路由 → 同一 Key 的消息有序(相同业务 ID)
  3. 幂等生产 → 配合 max.in.flight ≤ 5 保证顺序

5.4 性能优化

properties 复制代码
# 高性能 Producer 配置模板

# 批处理
batch.size=65536              # 64KB 批次
linger.ms=10                  # 10ms 延迟凑批
buffer.memory=134217728       # 128MB 缓冲区

# 压缩
compression.type=lz4          # 快速压缩

# 网络
max.in.flight.requests.per.connection=5  # 允许5个未确认请求

# 可靠性(在不丢消息的前提下优化性能)
acks=1                        # 仅 Leader 确认
retries=3                     # 有限重试

第六章:Kafka 消费者详解

6.1 消费流程

复制代码
Consumer 消费流程:

  1. Consumer 初始化
     - 加载配置
     - 连接 Bootstrap Server
     - 获取集群元数据

  2. 加入 Consumer Group
     - 发送 JoinGroup 请求
     - 选举 Group Leader
     - 接收分区分配方案

  3. 消息拉取 (Poll Loop)
     ┌─────────────────────────────────┐
     │  while (true) {                 │
     │    records = consumer.poll(1s)  │  ← 拉取消息
     │    process(records)             │  ← 处理消息
     │    consumer.commitSync()        │  ← 提交 Offset
     │  }                              │
     └─────────────────────────────────┘

  4. 偏移量提交
     - 自动提交(定时 5s)
     - 手动提交(commitSync / commitAsync)

6.2 关键参数配置

properties 复制代码
# === 拉取控制 ===

# fetch.min.bytes --- 最小拉取字节数
# Broker 积累到此字节数后再返回给消费者
# 默认 1(有数据立即返回)
fetch.min.bytes=1024  # 至少 1KB

# fetch.max.bytes --- 最大拉取字节数
# 单次 fetch 请求最大返回数据量
# 默认 52428800 (50MB)
fetch.max.bytes=52428800

# fetch.max.wait.ms --- 最大拉取等待时间
# 配合 fetch.min.bytes,到达此时间即使字节数不足也返回
fetch.max.wait.ms=500

# max.partition.fetch.bytes --- 单分区最大拉取字节数
# 默认 1048576 (1MB)
max.partition.fetch.bytes=1048576

# === 消费控制 ===

# max.poll.records --- 单次 poll 最多返回记录数
# 默认 500,建议根据消息大小和处理能力调整
max.poll.records=500

# max.poll.interval.ms --- 两次 poll 最大间隔
# 超过此时间消费者被认为失联,触发重平衡
# 默认 300000 (5min)
max.poll.interval.ms=600000  # 10min

# === 会话控制 ===

# session.timeout.ms --- 会话超时(默认 45s)
session.timeout.ms=45000

# heartbeat.interval.ms --- 心跳间隔(默认 3s)
# 应 < session.timeout.ms / 3
heartbeat.interval.ms=3000

# === Offset 策略 ===

# auto.offset.reset --- 无 Offset 时的初始策略
auto.offset.reset=earliest  # earliest / latest / none

# enable.auto.commit --- 自动提交
enable.auto.commit=false  # 推荐 false,手动提交

6.3 偏移量(Offset)管理

6.3.1 __consumer_offsets 主题
复制代码
__consumer_offsets 是 Kafka 内部 Topic,存储所有 Consumer Group 的 Offset:

┌──────────────────────────────────────────────────────┐
│  __consumer_offsets                                  │
│                                                     │
│  Key:   <GroupID, Topic, Partition>                  │
│  Value: <Offset, Metadata, Timestamp>               │
│                                                     │
│  示例:                                              │
│  Key:   (order-processor, orders, 0)                 │
│  Value: (offset=12345, metadata="", timestamp=...)  │
│                                                     │
│  特点:                                              │
│  - 默认 50 个分区                                     │
│  - 日志压缩策略 (compact)                             │
│  - 副本因子由 offsets.topic.replication.factor 决定   │
└──────────────────────────────────────────────────────┘
6.3.2 Offset 提交方式对比
复制代码
┌──────────────┬──────────────┬──────────────┬──────────────┐
│   提交方式    │   可靠性     │   吞吐量     │   适用场景    │
├──────────────┼──────────────┼──────────────┼──────────────┤
│  自动提交     │  低          │  高          │  简单场景     │
│  手动同步提交 │  高          │  低(阻塞)  │  金融/支付    │
│  手动异步提交 │  中          │  高          │  推荐首选     │
│  特定Offset  │  最高        │  自定义      │  精准控制     │
└──────────────┴──────────────┴──────────────┴──────────────┘

// 推荐模式:先处理,再异步提交
consumer.poll()
  → process(records)      // 成功处理
  → commitAsync()         // 异步提交
  → callback 中检查失败    // 失败告警

6.4 消费者组管理

复制代码
Consumer Group 内部协调:

  ┌──────────────────────────────────────────────────────────┐
  │                  Group Coordinator                        │
  │                  (某个 Broker)                            │
  │                                                          │
  │  职责:                                                   │
  │  - 维护 Group 成员列表                                    │
  │  - 触发/协调 Rebalance                                    │
  │  - 接收分区分配方案                                        │
  │  - 管理 Offset 提交                                       │
  │                                                          │
  │  Group Leader (某个 Consumer,不是 Broker)                 │
  │  职责:                                                   │
  │  - 执行分区分配策略 (PartitionAssignor)                    │
  │  - 将分配方案发送给 Coordinator                            │
  └──────────────────────────────────────────────────────────┘

Consumer Group 状态转换:
  Empty → PreparingRebalance → CompletingRebalance → Stable
                       ↑                                  │
                       └────────── 成员变更 ────────────────┘

6.5 消费者性能优化

java 复制代码
// === 多线程消费方案 ===

// 方案 1: 每个线程一个 Consumer(推荐)
// 每个 Consumer 独立消费不同 Partition
// 优点:简单,线程安全
// 缺点:线程数 ≤ 分区数
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; i++) {
    executor.submit(() -> {
        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
        consumer.subscribe(Arrays.asList("topic"));
        while (true) {
            ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(1));
            for (ConsumerRecord<String, String> record : records) {
                process(record);  // 同步处理
            }
            consumer.commitSync();
        }
    });
}

// 方案 2: 单 Consumer + 多处理线程
// 一个 Consumer poll,多个工作线程处理
// 缺点:Offset 管理复杂,可能丢失消息

第七章:Kafka 集群管理

7.1 集群扩容与缩容

7.1.1 Broker 扩容
bash 复制代码
# 1. 准备新节点(安装 Kafka,配置 server.properties)
#    node.id 必须唯一(选择未使用的 ID)
#    controller.quorum.voters 中不需要添加纯 Broker 节点

# 2. 格式化存储(使用相同的集群 UUID)
kafka-storage.sh format -t 1S9ggrMYQaCHBqfZy8hhOg \
  -c /opt/kafka/config/server.properties

# 3. 启动新 Broker
nohup kafka-server-start.sh /opt/kafka/config/server.properties &

# 4. 验证新 Broker 加入
kafka-metadata-quorum.sh --bootstrap-server localhost:9092 describe --status
# 检查 CurrentObservers 中是否包含新节点
7.1.2 分区重新分配
bash 复制代码
# 场景:将现有分区迁移到新 Broker

# 1. 生成迁移计划(JSON 文件)
cat > reassign.json << 'EOF'
{
  "topics": [{"topic": "test-basic"}],
  "version": 1
}
EOF

# 2. 生成建议的分配方案
kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
  --topics-to-move-json-file reassign.json \
  --broker-list "1,2,3,4" \
  --generate

# 3. 执行迁移
kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
  --reassignment-json-file reassign-execute.json \
  --execute

# 4. 验证迁移进度
kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
  --reassignment-json-file reassign-execute.json \
  --verify
7.1.3 Broker 缩容
bash 复制代码
# 1. 将要下线的 Broker 上的分区迁移到其他 Broker
#    (使用上面的 reassign 工具)

# 2. 迁移完成后,停止 Broker
kill <pid>

# 3. 如果下线的 Broker 是 Controller
#    → 集群自动执行 Controller 选举(无需手动干预)
#    → 检查新的 Active Controller:
kafka-metadata-quorum.sh --bootstrap-server localhost:9092 describe --status

7.2 Topic 管理

7.2.1 Topic 常用操作
bash 复制代码
# 创建 Topic
kafka-topics.sh --bootstrap-server localhost:9092 \
  --create --topic my-topic \
  --partitions 8 --replication-factor 3 \
  --config retention.ms=604800000 \
  --config cleanup.policy=delete

# 列出 Topic
kafka-topics.sh --bootstrap-server localhost:9092 --list

# 查看详情
kafka-topics.sh --bootstrap-server localhost:9092 \
  --describe --topic my-topic

# 增加分区(⚠️ 只能增加不能减少!)
kafka-topics.sh --bootstrap-server localhost:9092 \
  --alter --topic my-topic --partitions 12

# 修改配置
kafka-configs.sh --bootstrap-server localhost:9092 \
  --entity-type topics --entity-name my-topic \
  --alter --add-config retention.ms=259200000

# 删除 Topic
kafka-topics.sh --bootstrap-server localhost:9092 \
  --delete --topic my-topic
7.2.2 日志清理策略
复制代码
delete 策略(默认):
  根据 retention.ms / retention.bytes 删除旧消息
  适用场景:大多数业务消息

compact 策略:
  保留每个 Key 的最新值,删除旧版本
  适用场景:数据库 CDC、配置更新、状态快照

compact,delete 组合策略:
  先压缩,再按时间/大小删除
  适用场景:需要追溯变更历史,但保留时间有限

7.3 监控与告警

7.3.1 关键监控指标
复制代码
┌─────────────────────────────────────────────────────────────┐
│                Kafka 关键监控指标                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Broker 级别:                                               │
│  ├── BytesInPerSec / BytesOutPerSec (吞吐量)                 │
│  ├── MessagesInPerSec (消息速率)                              │
│  ├── TotalTimeMs (请求处理延迟)                               │
│  ├── RequestQueueSize (请求队列深度)                          │
│  ├── ActiveControllerCount (应为 1)                          │
│  ├── OfflinePartitionsCount (应为 0)                         │
│  └── UnderReplicatedPartitions (应为 0)                      │
│                                                             │
│  Consumer Group 级别:                                        │
│  └── RecordsLag (消费积压,关键!)                             │
│                                                             │
│  Producer 级别:                                              │
│  ├── record-send-rate (发送速率)                              │
│  ├── record-error-rate (错误率)                               │
│  └── request-latency-avg (平均延迟)                           │
│                                                             │
│  Topic 级别:                                                │
│  ├── BytesInPerSec / BytesOutPerSec                          │
│  └── Partition 级别 Leader/ISR 状态                          │
└─────────────────────────────────────────────────────────────┘
7.3.2 消费者 Lag 监控
bash 复制代码
# 查看 Consumer Group Lag
kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --group my-group --describe

# 输出示例:
# GROUP     TOPIC      PARTITION  CURRENT-OFFSET  LOG-END-OFFSET  LAG
# my-group  test-basic 0          15              15              0     ✓
# my-group  test-basic 1          12              20              8     ⚠️ 积压
# my-group  test-basic 2          8               8               0     ✓

# LAG > 0 → 消费者落后,需要关注
# LAG 持续增长 → 消费者处理能力不足

7.4 备份与恢复

7.4.1 MirrorMaker 2 跨集群复制
复制代码
MirrorMaker 2 是 Kafka 官方跨集群数据复制工具:

┌──────────────────┐         ┌──────────────────┐
│  DC-A (主集群)    │ ──────►│  DC-B (灾备集群)  │
│                  │ MM2     │                  │
│  topic-a         │────────►│  A.topic-a       │
│  topic-b         │────────►│  A.topic-b       │
│                  │         │                  │
│  消息自动同步      │         │  保持一致 Offset   │
└──────────────────┘         └──────────────────┘

MirrorMaker 2 特性:
  - 基于 Kafka Connect 框架
  - 支持 Active/Passive 和 Active/Active
  - 自动 Offset 同步
  - Topic 配置同步
7.4.2 灾难恢复方案
bash 复制代码
# 数据备份:定时备份日志目录
tar -czf /backup/kafka-data-$(date +%Y%m%d).tar.gz /opt/kafka/data/

# 恢复步骤:
# 1. 停止所有 Broker
# 2. 恢复数据目录
tar -xzf kafka-data-20260601.tar.gz -C /opt/kafka/
# 3. 重新格式化(⚠️ 会丢失数据!如果需要保留数据,跳过此步)
# 4. 按顺序启动 Controller 节点

第八章:Kafka 安全机制

8.1 认证机制

8.1.1 SSL/TLS 加密
properties 复制代码
# Broker 端 SSL 配置
listeners=SSL://0.0.0.0:9094
advertised.listeners=SSL://公网IP:9094

# SSL 证书配置
ssl.keystore.location=/opt/kafka/ssl/kafka.keystore.jks
ssl.keystore.password=changeit
ssl.key.password=changeit
ssl.truststore.location=/opt/kafka/ssl/kafka.truststore.jks
ssl.truststore.password=changeit

# 客户端 SSL 配置
security.protocol=SSL
ssl.truststore.location=/path/to/client.truststore.jks
ssl.truststore.password=changeit
8.1.2 SASL 认证
properties 复制代码
# === SASL/PLAIN ===
# Broker 端
listeners=SASL_PLAINTEXT://0.0.0.0:9095
sasl.enabled.mechanisms=PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN

# JAAS 配置文件
KafkaServer {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    username="admin"
    password="admin-secret"
    user_admin="admin-secret"
    user_producer="producer-secret"
    user_consumer="consumer-secret";
};

# === SASL/SCRAM (推荐,密码不传输) ===
# 创建 SCRAM 用户
kafka-configs.sh --bootstrap-server localhost:9092 \
  --alter --add-config 'SCRAM-SHA-256=[password=secret]' \
  --entity-type users --entity-name admin
8.1.3 完整安全配置
properties 复制代码
# 多层安全:SSL + SASL
listeners=SASL_SSL://0.0.0.0:9096
advertised.listeners=SASL_SSL://公网IP:9096
security.inter.broker.protocol=SASL_SSL

# SASL 配置
sasl.enabled.mechanisms=SCRAM-SHA-256
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-256

# SSL 配置
ssl.keystore.location=/opt/kafka/ssl/kafka.keystore.jks
ssl.keystore.password=changeit
ssl.truststore.location=/opt/kafka/ssl/kafka.truststore.jks
ssl.truststore.password=changeit

8.2 授权机制(ACL)

bash 复制代码
# 添加 ACL --- 允许 producer-user 对 my-topic 有写权限
kafka-acls.sh --bootstrap-server localhost:9092 \
  --add --allow-principal User:producer-user \
  --operation Write --topic my-topic

# 添加 ACL --- 允许 consumer-user 对 my-group 有读权限
kafka-acls.sh --bootstrap-server localhost:9092 \
  --add --allow-principal User:consumer-user \
  --operation Read --topic my-topic \
  --group my-group

# 查看 ACL
kafka-acls.sh --bootstrap-server localhost:9092 --list

# 删除 ACL
kafka-acls.sh --bootstrap-server localhost:9092 \
  --remove --allow-principal User:producer-user \
  --operation Write --topic my-topic

8.3 网络安全

properties 复制代码
# listener.security.protocol.map
# 定义可用协议名到安全协议的映射

listener.security.protocol.map=\
  PLAINTEXT:PLAINTEXT,\
  SSL:SSL,\
  SASL_PLAINTEXT:SASL_PLAINTEXT,\
  SASL_SSL:SASL_SSL,\
  CONTROLLER:PLAINTEXT

# 推荐生产环境配置:
# - 内网:PLAINTEXT (仅 Broker 间通信)
# - 外网:SASL_SSL (客户端连接)

第九章:Kafka Streams 与 KSQL

9.1 Kafka Streams 基础

复制代码
Kafka Streams 是构建在 Kafka 之上的轻量级流处理库:

架构特点:
  ┌─────────────────────────────────────────────┐
  │         Kafka Streams Application            │
  │                                             │
  │  ┌─────────────────┐  ┌─────────────────┐   │
  │  │ Stream Processor │  │  State Store    │   │
  │  │ (拓扑执行引擎)    │  │  (本地 RocksDB) │   │
  │  └────────┬────────┘  └────────┬────────┘   │
  │           │                    │             │
  │  ┌────────▼────────────────────▼─────────┐  │
  │  │        Kafka Cluster                    │  │
  │  │  Source Topic → Intermediate → Sink    │  │
  │  └────────────────────────────────────────┘  │
  │                                             │
  │  特点:                                     │
  │  - 无外部依赖(不依赖 Spark/Flink 集群)      │
  │  - 内置容错(利用 Kafka 分区和副本)           │
  │  - 状态存储支持(RocksDB/内存)               │
  │  - Exactly-Once 语义支持                     │
  │  - 弹性伸缩(增加实例即可)                    │
  └─────────────────────────────────────────────┘

9.2 流处理操作

java 复制代码
// === 无状态操作 ===

// map --- 一对一转换
stream.map((key, value) -> KeyValue.pair(key, value.toUpperCase()));

// filter --- 过滤
stream.filter((key, value) -> value.length() > 10);

// flatMap --- 一对多转换
stream.flatMap((key, value) -> {
    List<KeyValue<String, String>> results = new ArrayList<>();
    for (String word : value.split(" ")) {
        results.add(KeyValue.pair(key, word));
    }
    return results;
});

// === 有状态操作 ===

// groupBy + count --- 分组统计
KTable<String, Long> counts = stream
    .groupBy((key, value) -> value)
    .count();

// reduce --- 聚合
KTable<String, Long> sum = stream
    .groupByKey()
    .reduce((v1, v2) -> v1 + v2);

// join --- 连接两个流
KStream<String, String> joined = stream1.join(
    stream2,
    (v1, v2) -> v1 + "," + v2,
    JoinWindows.ofTimeDifferenceWithNoGrace(Duration.ofMinutes(5))
);

// === 窗口操作 ===
// Tumbling Window (滚动窗口,不重叠)
stream.groupByKey()
    .windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofMinutes(5)))
    .count();

// Hopping Window (滑动窗口,可重叠)
stream.groupByKey()
    .windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofMinutes(5))
        .advanceBy(Duration.ofMinutes(1)))
    .count();

9.3 KSQL 介绍

sql 复制代码
-- KSQL --- 使用 SQL 语法进行流处理

-- 创建流(从 Kafka Topic)
CREATE STREAM orders_stream (
    order_id VARCHAR,
    user_id VARCHAR,
    amount DOUBLE,
    order_time BIGINT
) WITH (
    KAFKA_TOPIC='orders',
    VALUE_FORMAT='JSON',
    TIMESTAMP='order_time'
);

-- 过滤查询
CREATE STREAM high_value_orders AS
SELECT * FROM orders_stream
WHERE amount > 1000;

-- 窗口聚合
CREATE TABLE hourly_stats AS
SELECT 
    user_id,
    COUNT(*) AS order_count,
    SUM(amount) AS total_amount,
    WINDOWSTART AS window_start,
    WINDOWEND AS window_end
FROM orders_stream
WINDOW TUMBLING (SIZE 1 HOUR)
GROUP BY user_id;

-- KSQL vs Kafka Streams:
-- KSQL: SQL 语法,快速原型,运维简单
-- Streams: Java API,灵活度高,性能极致

第十章:Kafka Connect 数据集成

10.1 Kafka Connect 概述

复制代码
Kafka Connect 是 Kafka 的数据集成框架:

┌──────────────────────────────────────────────────────────┐
│                  Kafka Connect 架构                        │
│                                                          │
│  ┌─────────────┐                    ┌─────────────┐      │
│  │   Source    │                    │    Sink     │      │
│  │  Connector  │                    │  Connector  │      │
│  │             │                    │             │      │
│  │  MySQL ────►│──── Kafka ────────►│──── ES      │      │
│  │  MongoDB ──►│                    │──── HDFS    │      │
│  │  File ─────►│                    │──── S3      │      │
│  └─────────────┘                    └─────────────┘      │
│                                                          │
│  运行模式:                                               │
│  Standalone: 单进程,适合开发测试                          │
│  Distributed: 多节点集群,生产环境                         │
└──────────────────────────────────────────────────────────┘

10.2 常用 Connector

properties 复制代码
# === JDBC Source Connector (MySQL → Kafka) ===
name=mysql-source-connector
connector.class=io.confluent.connect.jdbc.JdbcSourceConnector
tasks.max=1
connection.url=jdbc:mysql://192.168.0.54:3306/mydb
connection.user=root
connection.password=secret
table.whitelist=users,orders
mode=timestamp+incrementing
timestamp.column.name=updated_at
incrementing.column.name=id
topic.prefix=mysql-

# === Elasticsearch Sink Connector (Kafka → ES) ===
name=elasticsearch-sink-connector
connector.class=io.confluent.connect.elasticsearch.ElasticsearchSinkConnector
tasks.max=2
topics=mysql-users
connection.url=http://192.168.0.54:9200
type.name=_doc
key.ignore=true

10.3 Debezium CDC

复制代码
Debezium 是基于 Kafka Connect 的 CDC (Change Data Capture) 工具:

┌──────────────────────────────────────────────────────────┐
│                  Debezium CDC 流程                         │
│                                                          │
│  ┌─────────┐     ┌──────────────┐     ┌──────────┐      │
│  │  MySQL  │────►│   Debezium   │────►│  Kafka   │      │
│  │  binlog │     │  Connector   │     │  Topic   │      │
│  └─────────┘     └──────────────┘     └──────────┘      │
│                                                          │
│  捕获 INSERT/UPDATE/DELETE 事件                           │
│  输出格式 (JSON):                                         │
│  {                                                       │
│    "before": {"id": 1, "name": "Alice"},                 │
│    "after":  {"id": 1, "name": "Alice Updated"},         │
│    "op": "u",                                            │
│    "ts_ms": 1717228800000                                 │
│  }                                                       │
└──────────────────────────────────────────────────────────┘

第十一章:Kafka 性能优化

11.1 生产者性能优化

properties 复制代码
# 高吞吐 Producer 配置
batch.size=65536                    # 64KB 批次
linger.ms=10                        # 10ms 凑批延迟
buffer.memory=134217728             # 128MB 缓冲区
compression.type=lz4               # LZ4 压缩
acks=1                              # 仅 Leader 确认(吞吐优先)
max.in.flight.requests.per.connection=5  # 5 个并发请求

11.2 消费者性能优化

properties 复制代码
# 高吞吐 Consumer 配置
fetch.min.bytes=1048576            # 至少 1MB 才返回
max.poll.records=1000              # 单次拉取 1000 条
fetch.max.wait.ms=500              # 最多等 500ms
max.partition.fetch.bytes=10485760 # 单分区最多 10MB
复制代码
多线程消费策略:

┌─────────────────────────────────────────────────────────┐
│  推荐:每个线程一个 Consumer 实例                          │
│                                                         │
│  Thread 1 → Consumer 1 → poll() → process() → commit() │
│  Thread 2 → Consumer 2 → poll() → process() → commit() │
│  Thread 3 → Consumer 3 → poll() → process() → commit() │
│                                                         │
│  每个 Consumer 独立处理分配到的 Partition                 │
│  group.id 相同 → 属于同一 Consumer Group                 │
│  Kafka 自动分配 Partition 到 Consumer                   │
└─────────────────────────────────────────────────────────┘

11.3 Broker 性能优化

properties 复制代码
# === JVM 调优 ===
# KAFKA_HEAP_OPTS (在 kafka-server-start.sh 或环境变量)
export KAFKA_HEAP_OPTS="-Xmx6G -Xms6G"
export KAFKA_JVM_PERFORMANCE_OPTS="-server -XX:+UseG1GC \
  -XX:MaxGCPauseMillis=20 \
  -XX:InitiatingHeapOccupancyPercent=35 \
  -XX:+DisableExplicitGC"

# === 磁盘 IO 优化 ===
# 使用多个日志目录(多磁盘)
log.dirs=/data1/kafka,/data2/kafka,/data3/kafka

# === 网络优化 ===
num.network.threads=8              # CPU 核数
num.io.threads=16                  # CPU 核数 × 2
socket.send.buffer.bytes=1048576   # 1MB 发送缓冲
socket.receive.buffer.bytes=1048576 # 1MB 接收缓冲

# === 分区数量规划 ===
# 分区总数 = Σ(每个 Topic 的分区数)
# 建议:单 Broker 分区数 < 4000(总分区)
# 单 Broker Leader 分区数 < 2000

11.4 性能基准测试

本次实战性能数据:

复制代码
环境:华为云 ecs-7c2c, 2vCPU/4GiB, 4 Broker, 内网互联

Producer Benchmark (100,000 records, 256 bytes each, acks=1):
┌────────────────────┬─────────────────┐
│  指标               │  值              │
├────────────────────┼─────────────────┤
│  峰值吞吐            │ 13,675 msg/s    │
│  峰值带宽            │ 3.34 MB/s       │
│  P50 延迟            │ 56 ms           │
│  P95 延迟            │ 49,782 ms ※     │
│  总耗时              │ ~53 秒          │
└────────────────────┴─────────────────┘
※ 跨公网 ECS 节点间网络不稳定导致高延迟

Consumer Benchmark (50,000 records):
┌────────────────────┬─────────────────┐
│  指标               │  值              │
├────────────────────┼─────────────────┤
│  消费速率            │ 4,576 msg/s     │
│  消费带宽            │ 1.12 MB/s       │
│  总耗时              │ ~11 秒          │
└────────────────────┴─────────────────┘

第十二章:Kafka 运维与故障排查

12.1 日常运维

bash 复制代码
# === 每日检查清单 ===

# 1. 集群健康检查
kafka-metadata-quorum.sh --bootstrap-server localhost:9092 describe --status
# 检查: LeaderId, MaxFollowerLag (应为0或很小)

# 2. 检查未同步分区
kafka-topics.sh --bootstrap-server localhost:9092 --describe \
  | grep -v "Isr:.*,.*,"  # ISR 数量不足的

# 3. 检查消费者积压
kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --group <group_name> --describe

# 4. 磁盘使用
df -h /opt/kafka/data/
du -sh /opt/kafka/data/* | sort -rh | head -10

# 5. 日志检查
tail -100 /opt/kafka/logs/server.log | grep -E "ERROR|WARN"

12.2 常见故障排查

12.2.1 Broker 启动失败
复制代码
常见原因:

1. 端口被占用
   → netstat -tlnp | grep 9092
   → 或修改 listeners 端口

2. 存储格式化问题
   → 确保使用了相同的 cluster UUID
   → 重新格式化:rm -rf /opt/kafka/data && kafka-storage.sh format ...

3. Java 版本不兼容
   → Kafka 4.x 要求 Java 17+
   → java -version 确认

4. controller.quorum.voters 配置错误
   → 检查所有 Controller 节点配置一致
   → 检查 IP 和端口可达

5. 内存不足
   → 查看日志: grep OutOfMemory /opt/kafka/logs/server.log
   → 调整 KAFKA_HEAP_OPTS

实战案例 (kafka-04 启动失败):
  错误: Missing required configuration "controller.listener.names"
  解决: 添加 controller.listener.names=CONTROLLER

  错误: No readable meta.properties files found
  解决: 运行格式化命令(即使 Broker-only 节点也需要格式化)
12.2.2 消费者组重平衡问题
复制代码
常见原因:
1. max.poll.interval.ms 过小 → 处理时间超过 → 被踢出
2. session.timeout.ms 过小 → 网络抖动 → 被踢出
3. Consumer 频繁重启

排查:
  → 查看 Consumer 日志中的 JoinGroup/Rebalance 事件
  → 监控 Consumer Group 的 STATE (应为 Stable)

解决:
  → 增大 max.poll.interval.ms
  → 增大 session.timeout.ms
  → 使用 cooperative-sticky 分配策略
12.2.3 消息积压问题
复制代码
排查步骤:
1. 确认积压范围
   kafka-consumer-groups.sh --describe

2. 判断原因:
   消费速度 < 生产速度 → 扩容 Consumer
   消费逻辑慢 → 优化消费代码 / 增加线程
   分区数太少 → 增加分区(⚠️ 不能减少)

3. 临时方案:
   增加 Consumer 实例(水平扩容)
   减小 max.poll.records(加速心跳间隔)

12.3 数据一致性保障

复制代码
配置清单(消息不丢失):

Producer 端:
  acks=all
  enable.idempotence=true
  retries=MAX
  max.in.flight.requests.per.connection=5

Broker 端:
  default.replication.factor=3
  min.insync.replicas=2
  unclean.leader.election.enable=false

Consumer 端:
  enable.auto.commit=false  (手动提交)
  先处理消息,再提交 Offset

12.4 灾难恢复

复制代码
恢复优先级:
1. 启动 Controller Quorum (至少 N/2+1 个)
2. 启动剩余 Broker
3. 检查 ISR 状态
4. 检查消费者 Offset 恢复
5. 验证数据一致性

恢复检查清单:
✓ ClusterId 正确
✓ LeaderId 已选举
✓ MaxFollowerLag = 0
✓ ISR 完整
✓ 消费者可正常消费

第十三章:Kafka 实战项目案例

13.1 日志收集系统(Filebeat + Kafka + ELK)

复制代码
架构设计:

┌──────┐    ┌──────────┐    ┌────────┐    ┌────────────┐    ┌──────────┐
│ Apps │───►│ Filebeat │───►│ Kafka  │───►│ Logstash   │───►│ ES/Kibana│
│      │    │ (采集)    │    │ (缓冲)  │    │ (解析过滤) │    │ (存储展示)│
└──────┘    └──────────┘    └────────┘    └────────────┘    └──────────┘

优势:
  - Kafka 作为缓冲层,解耦采集和处理
  - Logstash 宕机不影响日志采集(Kafka 持久化)
  - 支持多个 Consumer Group(实时处理 + 离线归档)

13.2 实时数据管道(MySQL CDC)

复制代码
MySQL → Debezium → Kafka → Stream Processing → Sink

┌─────────┐   ┌──────────┐   ┌────────┐   ┌──────────┐   ┌──────┐
│  MySQL  │──►│ Debezium │──►│ Kafka  │──►│  Flink/  │──►│ HDFS │
│ (binlog)│   │ Connector│   │        │   │  Streams │   │  S3  │
└─────────┘   └──────────┘   └────────┘   └──────────┘   └──────┘

数据流转:
1. Debezium 捕获 MySQL binlog 变更
2. 写入 Kafka Topic (每表一个 Topic)
3. 流处理:清洗、转换、聚合
4. Sink Connector 写入目标存储

13.3 微服务事件驱动架构

复制代码
基于 Kafka 的 Event-Driven 微服务:

┌──────────┐  Event   ┌────────┐  Event   ┌──────────┐
│ 订单服务  │────────►│ Kafka  │────────►│ 库存服务  │
│          │ order   │        │ order   │          │
└──────────┘ created  └────────┘ created  └──────────┘
                            │
                            │ Event:    ┌──────────┐
                            │ order     │ 通知服务  │
                            │ created   │ (短信/邮件)│
                            └──────────►│          │
                                        └──────────┘

事件设计原则:
- 事件不可变(Immutable)
- 事件包含完整上下文(避免额外查询)
- 使用 Correlation ID 追踪链路
- 设计死信队列(DLQ)处理失败事件

第十四章:Kafka 新特性与未来

14.1 Kafka 4.x 新特性

14.1.1 KRaft 模式成为唯一选项
复制代码
Kafka 4.x 完全移除 ZooKeeper 相关代码:

变化:
  - 无 zookeeper.connect 配置
  - 无 ZK 依赖的启动脚本
  - 元数据 `@metadata` Topic 替代 ZK 存储
  - kafka-storage.sh format 替代 ZK 初始化

好处:
  ✓ 启动速度提升 10x+ (无需等待 ZK 连接)
  ✓ 元数据操作延迟降低 10-100x
  ✓ 支持百万级分区
  ✓ 运维复杂度大幅降低
14.1.2 Tiered Storage(分层存储)
复制代码
将冷数据自动迁移到廉价对象存储:

┌─────────────┐    ┌──────────────────┐
│ Local Disk  │───►│  S3 / HDFS / OSS │
│ (热数据)     │    │  (冷数据)         │
│ 最近 N 天    │    │  长期保留         │
└─────────────┘    └──────────────────┘

优势:
  - 本地磁盘只保留热数据
  - 对象存储保留全量历史
  - 消费者可透明访问冷数据
  - 降低存储成本 50-80%
14.1.3 Docker 容器化部署
yaml 复制代码
# docker-compose.yml for Kafka 4.3.0
version: '3.8'
services:
  kafka:
    image: apache/kafka:4.3.0
    ports:
      - "9092:9092"
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: broker,controller
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
      KAFKA_LOG_DIRS: /var/lib/kafka/data
    volumes:
      - kafka-data:/var/lib/kafka/data

volumes:
  kafka-data:

14.2 云原生 Kafka

服务 提供商 特点
Confluent Cloud Confluent 官方商业版,全托管,K8s 原生
AWS MSK Amazon AWS 托管,与 AWS 生态集成
Azure Event Hubs Microsoft 兼容 Kafka 协议
阿里云消息队列 Kafka 阿里云 国内首选,多 Region 部署
华为云 DMS Kafka 华为云 与华为云 ECS/CCE 集成

第十五章:Kafka 面试与进阶

15.1 面试高频问题

15.1.1 基础概念类
复制代码
Q1: Kafka 为什么快?
  - 顺序写入磁盘(追加写)
  - 零拷贝技术(sendfile)
  - Page Cache 利用
  - 批量压缩发送
  - 分区并行处理

Q2: Kafka 如何保证消息不丢失?
  - Producer: acks=all + 幂等性
  - Broker: RF=3 + min.insync.replicas=2 + unclean.leader.election.enable=false
  - Consumer: 手动提交 Offset + 先处理后提交

Q3: Kafka 如何保证消息顺序?
  - 分区内有序:相同 Key 路由到同一 Partition
  - 全局有序:单分区 Topic(牺牲吞吐)
  - 幂等生产者:max.in.flight.requests.per.connection ≤ 5
15.1.2 原理机制类
复制代码
Q4: ISR 是什么?什么情况下副本会从 ISR 中移除?
  - ISR = 与 Leader 保持同步的副本集合
  - 移除条件:超过 replica.lag.time.max.ms (30s) 未同步

Q5: HW 和 LEO 分别是什么?
  - LEO: 副本下一条待写入消息的 Offset
  - HW: 所有 ISR 副本都已确认的最高 Offset(消费者可见的边界)

Q6: Controller 的职责?
  - 分区管理、Leader 选举、Broker 上下线处理、元数据维护
15.1.3 实战应用类
复制代码
Q7: 消费者组重平衡的触发条件?
  - 消费者加入/离开
  - Topic 分区数变化
  - 消费者处理超时 (max.poll.interval.ms)

Q8: 如何处理消息积压?
  - 临时:增加 Consumer 实例
  - 长期:增加分区数、优化消费逻辑
  - 监控:RecordsLag 指标

Q9: Kafka 为什么使用 Pull 模式?
  - Consumer 可控制消费速度
  - 避免 Push 导致的 Consumer 过载
  - 支持批量拉取,提高吞吐

15.2 深度学习资源

资源 说明
《Kafka 权威指南(第2版)》 必读经典,覆盖原理+实战
Apache Kafka 官方文档 最权威的配置参考
Confluent 博客 最佳实践和新技术介绍
Kafka 源码 github.com/apache/kafka
Kafka Summit 演讲 业界实践分享

15.3 学习路线图

复制代码
初级(入门)→ 中级(实战)→ 高级(原理)→ 专家(架构)

初级:
  ✓ 理解消息队列概念
  ✓ 掌握 Kafka 核心概念(Topic/Partition/Broker/Offset)
  ✓ 能使用 CLI 工具操作 Kafka
  ✓ 能编写 Producer/Consumer 代码

中级:
  ✓ 理解副本机制、ISR、HW/LEO
  ✓ 能搭建和运维 Kafka 集群
  ✓ 掌握性能调优技巧
  ✓ 能处理常见故障

高级:
  ✓ 深入理解存储引擎、零拷贝、Page Cache
  ✓ 掌握 Kafka Streams/KSQL
  ✓ 能设计事件驱动架构
  ✓ 能进行集群容量规划

专家:
  ✓ 阅读和理解 Kafka 源码
  ✓ 能二次开发 Kafka 插件
  ✓ 能设计跨数据中心方案
  ✓ 能培训团队和推动 Kafka 落地

附录

附录 A:Kafka 常用命令速查

bash 复制代码
# ===== Topic 管理 =====
# 创建 Topic
kafka-topics.sh --bootstrap-server <host>:9092 --create \
  --topic <name> --partitions <N> --replication-factor <N>

# 列出 Topic
kafka-topics.sh --bootstrap-server <host>:9092 --list

# 查看 Topic 详情
kafka-topics.sh --bootstrap-server <host>:9092 --describe --topic <name>

# 增加分区
kafka-topics.sh --bootstrap-server <host>:9092 --alter \
  --topic <name> --partitions <N>

# 删除 Topic
kafka-topics.sh --bootstrap-server <host>:9092 --delete --topic <name>

# ===== 生产消费 =====
# 控制台生产者
kafka-console-producer.sh --bootstrap-server <host>:9092 --topic <name>

# 控制台消费者
kafka-console-consumer.sh --bootstrap-server <host>:9092 \
  --topic <name> --from-beginning

# ===== Consumer Group =====
# 列出所有 Group
kafka-consumer-groups.sh --bootstrap-server <host>:9092 --list

# 查看 Group 消费状态
kafka-consumer-groups.sh --bootstrap-server <host>:9092 \
  --group <name> --describe

# 重置 Offset
kafka-consumer-groups.sh --bootstrap-server <host>:9092 \
  --group <name> --topic <topic> --reset-offsets --to-earliest --execute

# ===== 集群管理 =====
# 查看 KRaft 状态
kafka-metadata-quorum.sh --bootstrap-server <host>:9092 \
  describe --status

# 查看 Broker 信息
kafka-broker-api-versions.sh --bootstrap-server <host>:9092

# ===== 性能测试 =====
# Producer 性能测试
kafka-producer-perf-test.sh --topic <name> \
  --num-records 100000 --record-size 256 --throughput -1 \
  --producer-props bootstrap.servers=<host>:9092 acks=1

# Consumer 性能测试
kafka-consumer-perf-test.sh --bootstrap-server <host>:9092 \
  --topic <name> --messages 50000

附录 B:配置参数详解

Producer 核心参数
参数 默认值 说明
bootstrap.servers --- Broker 地址列表
key.serializer --- Key 序列化器(全类名)
value.serializer --- Value 序列化器(全类名)
acks 1 确认机制(0/1/all)
retries MAX 重试次数
batch.size 16384 批次大小(字节)
linger.ms 0 延迟发送(毫秒)
buffer.memory 32MB 缓冲区大小
compression.type none 压缩算法(gzip/snappy/lz4/zstd)
max.request.size 1MB 请求最大大小
enable.idempotence true 幂等性(Kafka 3.x+ 默认开启)
max.in.flight.requests.per.connection 5 并发请求数
Consumer 核心参数
参数 默认值 说明
bootstrap.servers --- Broker 地址列表
group.id --- 消费者组 ID
auto.offset.reset latest 初始 Offset 策略(earliest/latest/none)
enable.auto.commit true 是否自动提交 Offset
auto.commit.interval.ms 5000 自动提交间隔
max.poll.records 500 单次拉取最大记录数
max.poll.interval.ms 300000 两次 poll 最大间隔
session.timeout.ms 45000 会话超时
heartbeat.interval.ms 3000 心跳间隔
fetch.min.bytes 1 最小拉取字节
fetch.max.wait.ms 500 最大等待时间
max.partition.fetch.bytes 1MB 单分区最大拉取字节
Broker 核心参数
参数 默认值 说明
process.roles --- KRaft 角色(broker/controller)
node.id --- Broker 唯一 ID
controller.quorum.voters --- Controller 仲裁节点
listeners PLAINTEXT://:9092 监听地址
advertised.listeners --- 对外公布的地址
log.dirs /tmp/kafka-logs 日志存储目录
num.partitions 1 新建 Topic 默认分区数
default.replication.factor 1 默认副本因子
min.insync.replicas 1 最小 ISR 数
log.retention.hours 168 日志保留时间(小时)
log.segment.bytes 1GB 日志段大小
offsets.topic.replication.factor 1 Offset Topic 副本因子
unclean.leader.election.enable false 是否允许非 ISR 副本当选 Leader

附录 C:性能测试工具使用

bash 复制代码
# === Producer 性能测试 ===
# 参数说明:
#   --num-records: 总消息数
#   --record-size: 每条消息字节数
#   --throughput: 限速(-1 表示不限速)
#   --producer-props: Producer 配置

# 基础吞吐测试
kafka-producer-perf-test.sh \
  --topic test-perf \
  --num-records 1000000 \
  --record-size 100 \
  --throughput -1 \
  --producer-props bootstrap.servers=localhost:9092 acks=1

# === Consumer 性能测试 ===
kafka-consumer-perf-test.sh \
  --bootstrap-server localhost:9092 \
  --topic test-perf \
  --messages 1000000

# === 端到端延迟测试 ===
# 使用 kafka-verifiable-producer/consumer
kafka-verifiable-producer.sh --bootstrap-server localhost:9092 \
  --topic test-latency --max-messages 10000

附录 D:常见问题 FAQ

复制代码
Q: 分区数可以减少吗?
A: 不能。只能增加不能减少。如需减少,需要删除重建 Topic。

Q: acks=all 时为什么还会丢消息?
A: 检查 min.insync.replicas 配置。如果 ISR 数 < min.insync.replicas,写入会失败(NotEnoughReplicas)。

Q: Kafka 适合作为任务队列吗?
A: 可以,但不如 RabbitMQ 方便。需要自行实现重试、延迟、死信等机制。
   RocketMQ 对任务队列场景更友好。

Q: Consumer Group 中的消费者数量可以超过分区数吗?
A: 可以,但多出的消费者会空闲。Kafka 保证一个 Partition 只分配给 Group 内一个 Consumer。

Q: KRaft 模式需要几个 Controller 节点?
A: 生产环境建议 3 个。3 节点可容忍 1 台故障,5 节点可容忍 2 台。必须为奇数。

Q: Kafka 消息默认保留多久?
A: 默认 7 天 (log.retention.hours=168)。可调整为更短(小时级)或更长(月级)。

Q: 如何查看某条特定 Offset 的消息?
A: 使用 kafka-console-consumer.sh 的 --offset 参数,或使用编程方式 seek() 到指定 offset。

附录 E:学习路线图

复制代码
Kafka 学习路径(建议 8 周):

Week 1-2:基础入门
  □ 理解消息队列概念与 Kafka 定位
  □ 掌握核心概念(Topic/Partition/Broker/Producer/Consumer)
  □ 单机安装 Kafka,使用 CLI 工具
  □ 阅读《Kafka 权威指南》第 1-3 章

Week 3-4:集群与 API
  □ 搭建多节点 KRaft 集群
  □ 编写 Producer/Consumer Java 代码
  □ 理解 acks、重试、幂等性
  □ 掌握 Offset 管理、Consumer Group

Week 5-6:内部机制
  □ 理解日志存储结构(Segment/Index)
  □ 深入副本机制(Leader/Follower/ISR/HW/LEO)
  □ 掌握 Controller 选举与 KRaft 共识
  □ 了解零拷贝、Page Cache 优化

Week 7-8:高级主题与实战
  □ Kafka Streams / KSQL 流处理
  □ Kafka Connect 数据集成
  □ 性能调优与监控
  □ 实战项目(日志收集/CDC/事件驱动)
  □ 安全配置(SSL/SASL/ACL)

附录 F:最佳实践总结

复制代码
Topic 设计:
  ✓ 使用有意义的命名(如 domain.entity.event)
  ✓ 合理设置分区数(根据吞吐预估)
  ✓ 生产环境 replication.factor ≥ 3
  ✓ 关键 Topic 设置 min.insync.replicas ≥ 2
  ✓ 使用合适的清理策略(delete vs compact)

Producer:
  ✓ 关键数据使用 acks=all
  ✓ 启用幂等性(enable.idempotence=true)
  ✓ 选择合适的压缩算法(lz4 推荐)
  ✓ 设置合理的 batch.size 和 linger.ms
  ✓ 始终处理 send() 的回调异常

Consumer:
  ✓ 使用手动提交 Offset(enable.auto.commit=false)
  ✓ 先处理消息,再提交 Offset
  ✓ 设置合理的 max.poll.records 和 max.poll.interval.ms
  ✓ 使用 CooperativeStickyAssignor 减少重平衡
  ✓ 监控 RecordsLag,及时处理积压

Broker:
  ✓ 使用独立磁盘存储日志
  ✓ Controller 节点配置 3 个(奇数)
  ✓ 设置合理的 JVM 堆大小(不超过 6GB)
  ✓ 监控关键指标(UnderReplicatedPartitions、ActiveControllerCount)
  ✓ 配置日志轮转和清理策略

安全:
  ✓ 公网访问必须使用 SSL/SASL
  ✓ 最小权限原则配置 ACL
  ✓ 内网通信使用 PLAINTEXT(性能最好)
  ✓ 启用审计日志

运维:
  ✓ 每日检查集群健康状态
  ✓ 监控消费者 Lag
  ✓ 定期备份关键数据
  ✓ 制定扩容/缩容方案
  ✓ 配置告警规则(ISR 不足、节点宕机、Lag 过高)

文档信息

实战集群:华为云 ecs-7c2c x 4 | Ubuntu 24.04 | Kafka 4.3.0 | KRaft

集群 UUID:1S9ggrMYQaCHBqfZy8hhOg

完成时间:2026-06-01

总字数:~25,000 字 | 代码示例:40+ | 图表:20+

相关推荐
chushiyunen1 小时前
elasticsearch笔记
笔记·elasticsearch·jenkins
dusk_star1 小时前
go语言--笔记--接口
java·笔记·golang
小陈phd1 小时前
多模态大模型学习笔记(四十二)——从像素到语义的精准问询——视觉问答(VQA)
笔记·学习
Irene19911 小时前
(课堂笔记)Kafka + Flume 完整实战
kafka·flume
Irene19911 小时前
Kafka + Flume 实操详情记录(略繁琐,包含错误和排查记录)
kafka·flume
Brilliantwxx1 小时前
【算法从零到千】【1-7】 双指针算法
开发语言·c++·笔记·算法·leetcode·推荐算法
wuyuanshun1 小时前
人工智能学习总结(一)
人工智能·学习
chushiyunen1 小时前
elasticsearch内置接口笔记
大数据·笔记·elasticsearch
吃好睡好便好1 小时前
詹姆斯·艾伦语录
学习·生活