Apache Kafka - 集群架构

2025年1月23日 | 阅读 15 分钟
Apache Kafka - Cluster Architecture

1. 代理(Brokers)

Kafka 集群由多个称为代理(brokers)的服务器组成。每个代理都由一个独特的 ID 标识,负责存储和管理数据、处理客户端请求以及在集群中复制数据。代理协同工作以提供一个分布式、容错且可扩展的系统。代理构成 Kafka 架构的核心,确保数据可靠存储并高效检索。

2. 主题(Topics)和分区(Partitions)

  • 主题:这些是数据发布和订阅的逻辑通道。主题是 Kafka 中数据分类的主要方式。
  • 分区:每个主题被分成多个段,这些段是按顺序排列的、不可变的记录序列。分区对于 Kafka 的可扩展性和容错性至关重要。它们允许数据分布在不同的代理上,促进并行处理和冗余。

分区通过分担负载,使 Kafka 能够处理大规模数据流。分区中的每条记录都分配有一个唯一的偏移量,作为其标识符并确保记录的顺序得到维护。

3. 生产者(Producers)

生产者是向 Kafka 主题发布数据的客户端应用程序。它们可以根据键将数据发送到特定的分区,确保具有相同键的记录进入同一分区。此功能对于维护相关记录的顺序至关重要。生产者被设计为高效,支持各种确认配置以确保数据可靠性。例如,生产者可以等待所有同步副本的确认,然后才认为记录已成功写入。

4. 消费者(Consumers)

消费者是能够从 Kafka 主题读取信息的客户端应用程序。它们被组织成消费者组,每个组充当一个逻辑订阅者。在一个组内,每个分区仅由一个消费者消费,从而实现并行数据处理,同时确保每条记录只处理一次。这种客户组机制通过分发职责来提升 Kafka 处理大量信息的能力。

5. ZooKeeper

ZooKeeper 是 Kafka 用于管理和协调代理的集中式服务。它处理关键任务,例如维护代理的元数据、管理配置、执行分区的领导者选举以及跟踪集群的健康状况。ZooKeeper 确保 Kafka 能够动态适应变化,例如代理故障,而不会丢失数据。

1. 设置 Kafka 集群

前提条件

在开始设置 Kafka 集群之前,请确保您拥有以下内容

  1. 服务器:用于运行 Kafka 代理的多台服务器(或虚拟机)。
  2. Java:Kafka 需要 Java 8 或更高版本。确保所有服务器上都安装并正确配置了 Java。
  3. Zookeeper:Kafka 使用 Apache Zookeeper 进行集群管理。Zookeeper 应安装并运行在一台或多台服务器上。

分步设置

下载 Kafka

从官方 Apache Kafka 网站获取最新的 Kafka 二进制文件。在您希望运行 Kafka 代理的每台服务器上解压存档。

配置 Zookeeper

确保 Zookeeper 已启动并运行。Kafka 需要一个正在运行的 Zookeeper 实例才能启动。

创建一个包含以下基本配置的 zoo.cfg 文件

在每个节点上启动 Zookeeper

配置 Kafka 代理

每个 Kafka 代理都需要一个唯一的配置文件。复制默认配置文件并为每个代理进行自定义。

为每个代理重复此操作,确保每个 broker.idlisteners 设置都是唯一的。

启动 Kafka 代理

使用自定义配置文件启动每个 Kafka 代理。

在每台服务器上使用各自的配置文件重复此命令。

验证集群

启动所有代理后,检查组是否正常工作。使用 Kafka 命令行工具列出主题并检查集群状态。

2. 代理配置和设置

正确配置 Kafka 代理对于最佳性能和可靠性至关重要。在此,我们将介绍 Kafka 代理配置文件 (server.properties) 中最重要的设置。

基本设置

1. broker.id:集群中每个代理的唯一标识符。它必须在所有代理中唯一。

2. listeners:指定代理侦听的主机名和端口。确保每个代理都是唯一的。

3. log.dirs:Kafka 存储其日志文件的目录。它可以是逗号分隔的目录列表,以获得更好的性能。

4. zookeeper.connect:Zookeeper 连接字符串。这是逗号分隔的 Zookeeper 服务器地址列表。

性能调优

1. num.network.threads:处理网络请求的线程数。如果代理正在处理许多客户端连接,请增加此值。

2. num.io.threads:用于磁盘 I/O 操作的线程数。将其设置为磁盘数量或更高,以提高性能。

3. socket.send.buffer.bytessocket.receive.buffer.bytes:TCP 发送和接收缓冲区的大小。

4. log.retention.hours:保留日志段的持续时间。根据您的数据保留策略设置此值。

5. log.segment.bytes:单个日志段文件的最大大小。根据存储容量和性能需求进行调整。

可靠性和持久性

1. replication.factor:自动创建主题的默认复制因子。确保此值足够高以容忍代理故障。

2. min.insync.replicas:必须确认写入才能被视为成功的最小副本数。此设置确保数据持久性。

3. unclean.leader.election.enable:控制是否允许不干净的领导者选举。不干净的选举可能导致数据丢失,但可能会提高可用性。

安全设置

1. listeners:使用 SSL 等安全协议定义侦听器。

2. ssl.keystore.locationssl.keystore.password:配置代理的 SSL 密钥库位置和密码。

3. ssl.truststore.locationssl.truststore.password:配置代理的 SSL 信任库位置和密码。

4. ssl.client.auth:配置客户端身份验证。

监控和管理

1. metrics.recording.level:设置指标记录的详细级别。

2. jmx.port:为 Kafka 启用 JMX 监控。

3. log.retention.check.interval.ms:检查日志保留的频率。

3. Zookeeper 在 Kafka 集群管理中的作用

Apache Kafka 在各种集群管理任务上严重依赖 Zookeeper。Zookeeper 的作用对于维护 Kafka 集群的整体健康和稳定性至关重要。

以下是 Zookeeper 如何支持 Kafka 的详细介绍

集群元数据管理

Zookeeper 维护 Kafka 集群的元数据,其中包括有关代理、主题和分区的信息。它存储

  1. 代理元数据:有关每个代理的信息,例如其 ID、主机和端口。
  2. 主题元数据:有关主题的详细信息,包括分区列表及其各自的副本。
  3. 分区分配:分区到代理的映射,包括哪个代理是领导者,哪个是追随者。

领导者选举

Zookeeper 处理分区的领导者选举过程。当领导者代理失败时,Zookeeper 协调在同步副本中选举一个新的领导者。这确保始终有领导者可用以处理客户端请求,从而维护分区的可用性。

配置管理

Kafka 使用 Zookeeper 存储和管理代理和主题的配置信息。这允许动态更新配置,而无需重新启动代理。Zookeeper 管理的配置数据包括

  1. 代理配置:可在运行时动态更新的配置。
  2. 主题配置:主题级别的配置,例如保留策略和复制因子。

健康监测

Zookeeper 持续监控 Kafka 代理的健康状况。它跟踪每个代理的状态并检测故障。如果代理失败,Zookeeper 会迅速将其从集群的元数据中删除,触发分区重新分配和领导者选举过程。

配额管理

Kafka 使用 Zookeeper 管理生产者和消费者的配额。配额控制数据生产和消费的速率,防止任何单个客户端使集群过载。Zookeeper 存储并强制执行这些配额设置。

安全和 ACL

Zookeeper 管理 Kafka 的访问控制列表 (ACL)。ACL 用于控制哪些用户和应用程序可以对主题和代理执行特定操作。Zookeeper 存储这些 ACL 并强制执行访问控制策略,从而增强 Kafka 集群的安全性。

Zookeeper for Kafka 的设置和配置

1. 下载 Zookeeper

从官方 Apache Zookeeper 网站获取最新版本的 Zookeeper。在您希望运行 Zookeeper 节点的每台服务器上解压存档。

2. 创建配置文件

创建一个包含必要设置的 zoo.cfg 文件。将此文件放在 Zookeeper 安装的 conf 目录中。

3. 设置数据目录

在每台服务器上创建 zoo.cfg 中指定的数据目录。

4. 启动 Zookeeper

使用以下命令在每个节点上启动 Zookeeper

5. 验证 Zookeeper 集群

检查 Zookeeper 节点的状态,确保它们正确连接并形成法定人数。

Kafka 集群架构

Apache Kafka 是一个分布式事件流平台,专为高吞吐量和低延迟消息传递而设计。了解 Kafka 的集群架构对于高效管理和利用其功能至关重要。

本指南深入探讨了构成 Kafka 架构的核心组件和机制,包括 Kafka 代理、主题和分区、数据复制和容错、数据分发和负载平衡以及代理和分区领导力。

Apache Kafka - Cluster Architecture

Kafka 代理:概述

Kafka 代理是处理消息容量、分发和检索的服务器。每个代理负责维护消息日志、处理客户端请求并确保数据复制。代理在集群中协同工作以提供容错性和高可用性。

  • 代理 ID:Kafka 组中的每个代理都被分配一个称为代理 ID 的唯一标识符。
  • 侦听器:代理在指定的网络地址和端口上侦听客户端连接。
  • 日志管理:代理将消息存储在磁盘上的日志文件中,按主题和分区组织。
  • Zookeeper 集成:代理使用 Zookeeper 进行元数据管理和协调。

代理配置

每个代理都使用属性文件(例如 server.properties)进行配置。关键配置参数包括

  • broker.id:每个代理的唯一标识符。
  • listeners:客户端连接的网络地址和端口。
  • log.dirs:存储日志文件的目录。
  • zookeeper.connect:Zookeeper 连接字符串。

server.properties 示例:

启动 Kafka 代理

要启动 Kafka 代理,请使用以下命令

此命令使用指定的配置初始化代理,并将其连接到 Zookeeper 集群进行元数据管理。

Kafka 主题和分区

Kafka 主题

Kafka 中的主题是用于组织和分类消息的逻辑通道。生产者将消息发布到主题,消费者订阅主题以接收消息。

  • 主题创建:主题可以由生产者动态创建,也可以使用 Kafka 工具显式创建。
  • 配置:主题具有可配置参数,例如复制因子、分区和保留策略。

创建主题的示例

分区

分区是 Kafka 中并行性和可扩展性的基本单位。每个主题被划分为多个分区,这允许 Kafka 分担负载并横向扩展。

  • 数据分发:分区使信息能够在不同代理之间分发。
  • 并行处理:消费者可以并行从多个分区读取,从而提高吞吐量。
  • 顺序:Kafka 确保单个分区内的消息请求,但不跨分区。

数据复制

Kafka 通过在多个代理之间复制分区来确保容错性。复制因子决定了每个分区的副本数量。

  • 领导者和追随者:每个段有一个先锋和至少一个追随者副本。领导者处理所有读写操作,而追随者复制领导者的数据。
  • 同步副本 (ISR):完全找到先锋的模仿排列。

配置复制因子为 3 的主题示例

容错性

  • 领导者选举:当领导者代理失败时,Zookeeper 协调从 ISR 中选举一个新的领导者。
  • 数据持久性:Kafka 通过复制确保数据持久性,使其能够在不丢失数据的情况下从代理故障中恢复。

数据分发

Kafka 将数据分发到分区以平衡负载并确保高效的数据检索。

  • 分区策略:生产者可以利用分区策略来控制消息如何分散在段中。常见策略包括轮询和基于键的分区。

具有自定义分区的生产者示例

负载均衡

  • 消费者组:买家组中的客户分担从一个点消费消息的责任。每个分区仅分配给组内的一个消费者,从而平衡负载。
  • 重新平衡:当消费者组成员发生变化时(例如,新的消费者加入或离开),Kafka 会在消费者之间重新平衡分区,以均匀分配负载。

代理领导力

  • 集群控制器:其中一个代理充当集群控制器,负责管理主题元数据、将分区分配给代理以及监控代理健康状况等管理任务。

分区领导力

  • 领导者和追随者:每个段有一个先锋商家和一些支持者商家。领导者处理该分区的​​所有客户端请求,而追随者复制数据。
  • 领导者选举:当当前领导者失败时,Zookeeper 协调选举一个新的领导者,确保分区的持续可用性。

检查分区领导力的示例

此命令提供有关分区领导者及其副本的详细信息。

示例程序

生产者示例

以下是一个 Kafka 生产者发送消息到主题的 Java 示例

示例输出

Apache Kafka - Cluster Architecture

消费者示例

以下是一个 Kafka 消费者从主题读取消息的 Java 示例

输出

Apache Kafka - Cluster Architecture

这些示例说明了如何设置基本的 Kafka 生产者和消费者。对于更高级的配置,例如自定义分区器、序列化器和复杂的消费者组管理,请参阅官方 Kafka 文档和相关 API 参考。

Kafka 内部原理

了解 Kafka 的内部原理,包括消息存储、日志管理、数据保留策略、索引、段文件以及压缩和序列化机制,对于优化 Kafka 性能和确保数据可靠性至关重要。

Apache Kafka - Cluster Architecture

消息存储和日志管理

Kafka 将消息存储在分布式日志中,其中每个主题都分为多个分区。每个分区是一个有序、不可变的消息序列,持续附加到提交日志中。

  • 日志文件:每个分区内的消息存储在磁盘上的日志文件中。这些日志文件被分成段,以便于管理和高效的 I/O 操作。
  • 分段日志结构:每个分区的日志都分成段。当当前段达到预定义的大小或时间限制时,会创建一个新的段文件。这种分段有助于管理磁盘空间并提高读/写效率。
  • 顺序写入:Kafka 的存储模型利用顺序磁盘写入,这比随机写入快得多,从而确保消息生产的高吞吐量。

数据保留和清理策略

Kafka 根据可配置的保留策略保留消息,这些策略决定消息存储多长时间或它们占用多少空间。

  • 基于时间的保留:消息保留预定时间,之后将被删除。这由 log.retention.hours 设置控制。
  • 基于大小的保留:Kafka 可以删除旧消息,以确保主题的日志文件总大小不超过配置的限制,该限制由 log.retention.bytes 定义。
  • 日志清理:Kafka 支持两种清理策略
    删除:当满足保留条件时,旧段将被删除。
    压缩:仅保留每个键的最新值,并丢弃旧值。这对于变更日志流等场景很有用。

索引和段文件

Kafka 维护索引文件以快速定位日志段中的消息。

  • 索引文件:每个日志部分都有一个相关的记录文档,用于指导消息抵消到它们在日志文档中的实际位置。这允许高效地查找和检索消息。
  • 时间索引文件:Kafka 还会创建时间索引文件,将时间戳映射到偏移量,从而实现基于时间的消息查找。
  • 段结构:分区的数据存储在多个段文件中,每个文件包含分区消息的一部分。段文件根据它们包含的第一个消息的偏移量命名。

压缩和序列化

Kafka 支持各种压缩和序列化程序,以增强容量和组织使用。压缩:生产者可以在将消息发送到 Kafka 之前对其进行压缩。支持的压缩类型包括 GZIP、Snappy、LZ4 和 ZSTD。压力减少了通过组织传输和存储在板上的数据量,从而进一步提高了执行力。

compression.type=gzip # 选项:none, gzip, snappy, lz4, zstd

序列化:Kafka 要求消息序列化为字节数组。常见的序列化格式包括

  • StringSerializer:将字符串转换为字节。
  • ByteArraySerializer:用于原始字节数组。
  • AvroSerializer:使用 Avro 模式进行紧凑快速的序列化。
  • ProtobufSerializer:利用 Protocol Buffers 进行高效序列化。

压缩和序列化的生产者配置示例

案例研究和最佳实践

Apache Kafka 在各行各业广泛应用于实时数据流、事件溯源和高吞吐量消息系统。本节将探讨 Kafka 集群部署的真实案例、维护 Kafka 集群的最佳实践以及常见的陷阱。

Apache Kafka - Cluster Architecture

Kafka 集群部署的真实案例

1. LinkedIn

用例:Kafka 的创建者 LinkedIn 广泛使用它进行实时分析和监控。Kafka 每天处理数万亿条消息,跨越数千个 Kafka 代理。

部署策略

  • 多数据中心复制:LinkedIn 使用 MirrorMaker 将 Kafka 部署到多个数据中心以复制数据。这确保了高可用性和灾难恢复。
  • 实时分析:Kafka 将数据流传输到 Apache Samza 进行实时分析,使 LinkedIn 能够实时处理和分析数据流。
  • 运营监控:Kafka 用于日志聚合和监控,提供系统运营和用户活动的实时可见性。

2. Uber

用例:Uber 依靠 Kafka 进行实时事件处理,并支持其复杂的、数据驱动的基础设施。Kafka 每天处理数十亿条消息,用于各种应用程序,包括乘车匹配、欺诈检测和用户活动跟踪。

部署策略

  • 高可用性:Uber 通过跨多个可用区部署集群来确保 Kafka 的高可用性。他们使用 Apache Helix 等工具来管理分区重新平衡和故障转移。
  • 流处理:Uber 将 Kafka 与 Apache Flink 集成,进行实时流处理,使他们能够快速做出数据驱动的决策。
  • 可扩展性:Uber 的 Kafka 部署专为可扩展性而设计,允许系统高效处理峰值负载并确保低延迟。

3. Netflix

用例:Netflix 使用 Kafka 进行数据管道管理、实时分析和监控。Kafka 帮助 Netflix 管理其流媒体服务产生的大量数据。

部署策略

  • 微服务架构:Kafka 作为 Netflix 微服务架构的骨干,促进服务之间的通信。
  • 数据管道:Kafka 用于从不同来源(包括客户端连接、日志和测量值)摄取和处理信息。然后,这些数据由 Apache Spark 处理并存储在 Amazon S3 中。
  • 监控和警报:Kafka 帮助 Netflix 实时监控系统性能和用户活动,从而实现主动事件管理。

维护 Kafka 集群的最佳实践

1. 集群规划和设置

  • 容量规划:估算您的吞吐量和存储要求,以确定代理、分区和复制因子的数量。考虑未来的增长和可扩展性。
  • 硬件配置:为 Kafka 日志使用专用磁盘,以防止 I/O 争用。选择高吞吐量 SSD,并确保足够的 RAM 和 CPU 资源。
  • 网络配置:确保高速、低延迟的网络。为内部和外部流量配置单独的网络接口,以防止干扰。

2. Zookeeper 配置

  • Zookeeper 集群:部署奇数个 Zookeeper 节点(通常是三到五个),以确保基于法定人数的决策。确保 Zookeeper 节点位于单独的机器上,以避免单点故障。
  • 配置调优:根据您的集群大小和性能要求调整 Zookeeper 设置,例如 tickTime、initLimitsyncLimit
  • 监控和维护:定期监控 Zookeeper 的健康状况和性能。使用 Exhibitor 等工具进行 Zookeeper 管理,并确保正确的备份和恢复程序。

3. 代理配置和管理

  • 代理设置:根据您的工作负载优化代理设置,例如 num.network.threads、num.io.threadssocket.send.buffer.bytes。配置适当的日志保留策略。
  • 分区管理:在代理之间平衡分区以避免热点。添加新代理或进行维护时,使用分区重新分配工具重新分配分区。
  • 监控:持续监控代理指标,例如 CPU、内存、磁盘使用情况和网络 I/O。Prometheus 和 Grafana 等工具可以帮助可视化这些指标并设置异常警报。

4. 主题和分区管理

  • 主题配置:为主题配置适当数量的分区,以平衡负载并最大化并行性。对于关键数据,使用更高的复制因子以确保可靠性。
  • 保留策略:根据信息使用模式设置维护安排。根据需要使用时间敏感或基于大小的维护。
  • 压缩:对于受益于保留每个键最新记录的主题(例如,变更日志流),启用日志压缩。