Kafka 架构详解:核心组件及其角色
探索 Apache Kafka 分布式事件流架构的基本组成部分。本指南清晰地阐述了 Kafka Broker、Topic、Partition、Producer、Consumer 的角色,以及 ZooKeeper 的协调作用。了解这些组件如何协同工作,以确保高吞吐量、容错的数据处理和存储,这是任何 Kafka 实施所需的关键知识。
Kafka架构详解:核心组件及其角色
Kafka架构初看可能令人困惑,因为同一系统处理存储、流式传输、复制和消费者进度。一旦分离主要部分,模型就变得简单多了:生产者将记录写入主题分区,Broker存储这些分区,消费者按偏移量读取记录。
本指南解释Kafka核心组件及其在真实集群中的协作方式。
Broker:Kafka服务器
Kafka集群由一个或多个Broker组成。Broker是存储分区数据并处理来自生产者和消费者的客户端请求的Kafka服务器。
当生产者发送记录时,它写入当前领导目标分区的Broker。当消费者读取记录时,它从提供该分区的Broker获取。在正常设置中,每个Broker处理来自许多主题的许多分区。
增加Broker可以增加存储容量并分散流量,但不会自动解决所有瓶颈。您还需要足够的分区、平衡的副本放置、健康的磁盘和网络容量。
主题:命名的记录流
主题是命名的记录流,例如orders、payments或user_activity。生产者写入主题,消费者订阅主题。
主题被分割成分区。每个分区是一个有序的、仅追加的日志。Kafka保证单个分区内的记录顺序,而不是整个主题。
这个细节很重要。如果某个客户的所有事件必须按顺序处理,请使用稳定的键,例如customer_id。Kafka的默认分区器使用键来选择分区,因此具有相同键的记录通常进入同一分区。
分区和偏移量
分区中的每条记录都有一个偏移量。偏移量是一个标识记录在该分区中位置的数字。
例如,一个名为orders的主题有三个分区,可能如下所示:
orders-0: 偏移量 0, 偏移量 1, 偏移量 2
orders-1: 偏移量 0, 偏移量 1
orders-2: 偏移量 0, 偏移量 1, 偏移量 2, 偏移量 3
偏移量仅在其自己的分区内有意义。orders-2中的偏移量3与另一个分区中的偏移量3无关。
分区为Kafka提供并行性。更多分区允许同一消费者组中的更多消费者同时工作,在该组中每个分区最多有一个活跃消费者。
复制和领导者
Kafka使用复制来在Broker故障时保持数据可用。每个分区可以在不同Broker上有多个副本。
一个副本是领导者。生产者和消费者通常与该分区的领导者通信。其他副本是追随者。追随者从领导者复制数据,并准备好在领导者故障时接管。
复制因子控制Kafka保留的副本数量。复制因子为3意味着Kafka在三个Broker上存储每个分区的三个副本,前提是有足够的Broker可用。
您可以像这样创建一个主题:
kafka-topics.sh --create \
--topic user_activity \
--bootstrap-server localhost:9092 \
--partitions 3 \
--replication-factor 3
该命令需要一个至少有三个Broker的集群。在单Broker本地设置中,使用复制因子1。
生产者:写入事件的应用程序
生产者向Kafka主题发送记录。一条记录可以包含键、值、时间戳和标头。
生产者首先向集群请求元数据,以了解哪个Broker领导每个分区。然后它将记录直接发送到正确的Broker。
生产者的可靠性在很大程度上取决于设置,例如:
| 设置 | 影响 |
|---|---|
acks |
写入成功前需要多少个Broker确认 |
retries |
生产者是否重试临时故障 |
enable.idempotence |
帮助避免生产者重试导致的重复 |
compression.type |
减少许多工作负载的网络和磁盘使用 |
对于重要数据,通常使用acks=all,因为领导者在确认写入之前等待同步副本。确切行为还取决于Broker设置,例如min.insync.replicas。
消费者和消费者组
消费者从主题读取记录。大多数生产环境中的消费者在消费者组内运行。
在一个消费者组内,Kafka一次只将每个分区分配给一个活跃消费者。这就是Kafka如何让您扩展处理同时保持每个分区内顺序的方式。
例如,如果orders有三个分区,并且您的服务在同一消费者组中有三个消费者,则每个消费者可以处理一个分区。如果您向同一组添加第四个消费者,一个消费者将空闲,因为只有三个分区可分配。
不同的消费者组获得独立的读取。您的计费服务和分析服务都可以读取orders主题,而不会互相窃取记录。
偏移量和消费者进度
消费者通过提交偏移量来跟踪进度。Kafka将消费者组的已提交偏移量存储在名为__consumer_offsets的内部主题中。
如果消费者崩溃并重新启动,它将使用已提交的偏移量恢复。提交的时间影响处理行为:
| 提交时机 | 可能的结果 |
|---|---|
| 处理完成前提交 | 崩溃可能导致跳过记录 |
| 处理完成后提交 | 崩溃可能导致重新处理记录 |
许多系统选择至少一次处理:先处理记录,然后提交偏移量。这可能在崩溃后产生重复,因此下游写入应尽可能幂等。
集群元数据:ZooKeeper和KRaft
较旧的Kafka集群使用Apache ZooKeeper管理集群元数据和控制器选举。许多现有安装仍以这种方式运行。
较新的Kafka部署可以使用KRaft模式,即Kafka内置的元数据仲裁。在KRaft集群中,Kafka不再依赖ZooKeeper进行元数据管理。
当您阅读较旧的Kafka教程时,请检查它们假设使用ZooKeeper还是KRaft。命令、配置文件和操作步骤可能不同。
记录如何通过Kafka移动
典型的写入和读取流程如下:
- 生产者连接到引导Broker并获取元数据。
- 生产者根据记录键或分区策略选择分区。
- 生产者将记录发送到该分区的领导者Broker。
- 领导者将记录追加到其日志,追随者复制它。
- 领导者根据生产者的
acks设置确认写入。 - 消费者轮询分区并从其当前偏移量开始接收记录。
- 消费者处理记录并为其消费者组提交偏移量。
这个流程解释了为什么Kafka可以同时支持实时处理和重放。消费者在读取记录时不会删除它们。
保留:Kafka按策略保留数据
Kafka不是传统的队列,消息一旦被消费者读取就消失。Kafka根据保留设置保留记录。
常见的主题设置包括:
retention.ms=604800000
retention.bytes=10737418240
retention.ms控制基于时间的保留。retention.bytes控制基于大小的保留。实际清理还取决于段设置和Broker配置。
某些主题使用日志压缩代替或结合基于删除的保留。压缩保留每个键的最新值,这对于状态类主题(如用户配置文件或配置更改)很有用。
需要记住的内容
Kafka的架构围绕分区日志构建。Broker存储分区,生产者写入分区领导者,消费者按偏移量读取,消费者组跨分区分配工作。
当您设计Kafka主题时,请同时考虑顺序、分区数量、复制因子、保留和消费者组行为。这些选择决定了您的系统如何扩展、从故障中恢复以及重放旧事件。