Apache Kafka – 集群架构

Apache Kafka 到目前为止已经非常适合开发可靠的互联网规模的流应用程序,这些应用程序还具有容错能力,并且能够处理实时和可扩展的需求。在本文中,我们将重点介绍 Java 中的 Kafka 集群架构。

在本文中,我们将了解 Apache Kafka – 集群架构。

在深入研究集群架构之前,我们先了解一下 Apache Kafka 的一些基本概念,打好基础。

1. 发布-订阅模型
Kafka 采用发布-订阅模型,其中数据生产者将记录发布到主题,数据消费者订阅这些主题以接收和处理数据。生产者和消费者的这种解耦允许可扩展且灵活的数据处理。

2. Topic主题和分区
主题是对数据进行分类和组织的逻辑通道。在每个主题中,数据被进一步划分为多个分区,从而实现跨多个代理的并行处理和高效负载分配。

3. 代理broker
代理(经纪者)是存储和管理数据的单个 Kafka 服务器。他们负责处理数据复制、客户端通信,并确保 Kafka 集群的整体健康状况。

Kafka集群架构的关键组件
Kafka集群架构的关键组件涉及以下内容:
Brokers——Kafka集群中的节点
代理的职责:

  • 数据存储:Broker提供数据存储能力;因此,他们为Kafka集群提供了分布式存储质量。
  • 复制:代理负责数据复制,这是培育高可用性系统的冗余保证。
  • 代理沟通:代理是中间人,通过充当此过程中的链接来帮助将数据从供应商转移到消费者。

代理之间的沟通和协调:
  • 代理间通信:运行容错且可扩展的分布式系统(例如 Kafka 集群)需要代理之间进行有效的通信,以实现同步和负载平衡。
  • 集群元数据管理:代理集中控制与主题、分区和消费者组的元数据相关的数据集,以确保单一的集群状态。

// Code example for creating a Kafka producer and sending a message
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
ProducerRecord<String, String> record = new ProducerRecord<>("example-topic", "key", "Hello, Kafka!");
producer.send(record);
producer.close();


Topic主题 – 数据组织的逻辑通道
Kafka 中主题的作用:

  • 数据组织:Kafka 在该主题下的功能之一是其分类和预测技术。
  • 可扩展的数据组织:主题作为分发数据集的框架,通过消息提供并行化。

主题分区策略:
  • 分区逻辑:分区携带来自分区逻辑的标签或键,这是将消息扔到更多推送的方法。
  • 平衡工作负载:基本的是Broker内的平均工作负载分配,这有助于处理快速数据。

分区——增强并行性和可扩展性
分区逻辑:

  • 确定性分区:分区算法可能是确定性的,否则系统可以在一致的基础上将消息分配给分区。
  • 基于密钥的分区:明文分区的密钥将用于确定分区,这保证了相同密钥的消息始终进入同一分区,因此具有不同密钥的消息会进入不同的分区。

分区在数据分布中的重要性:
  • 并行处理:分区消息可以导致处理工作负载的并行执行,从而提高链路容量。
  • 负载分配:分区实现多个代理之间的混合数据工作负载,使后者不会成为瓶颈并最大限度地减少使用的资源。

复制——确保容错
复制在 Kafka 中的作用:

  • 数据持久性:重复使数据持久化,确保每个分区的不同副本存储在不同的代理中。
  • 高可用性:复制是一项用于提供高系统可用性的功能,因为这允许系统在某些代理性能不佳甚至出现故障时继续运行。

领导者-跟随者复制模型:
  • Leader-Replica 关系:每个分区有一个头,以及与其相等的追随者数量。Leader 的任务是处理数据写入,Follower 然后复制需要容错的数据。
  • 故障转移机制:这种共识如何发挥作用?一个追随者崛起并取代先前停止运行的领导者,从而使系统循环继续运行和数据完整性。

// 创建 Kafka Consumer 并订阅主题的代码示例
KafkaConsumer<String, String> Consumer = new KafkaConsumer<>(props); 
Consumer.subscribe(Collections.singletonList("example-topic")); 
while (true) { 
    ConsumerRecords<String, String> 记录 = Consumer.poll(Duration.ofMillis(100)); 
    for (ConsumerRecord<String, String> record :records) { 
        System.out.printf("收到消息:key=%s,value=%s%n", record.key(), record.value()); 
    }


Kafka集群内的数据流
了解生产者和消费者的工作流程对于掌握 Kafka 集群内数据传输的动态至关重要。
– 生产者 – 启动数据流:
kafka的生产者:

  • 数据启动:Kafka 消费者的主要工作围绕消费数据,通过生产者将记录推送到分配的主题来促进数据的消费。
  • 异步消息传递:生产者可以发送异步消息,并且由于集群外决策不需要 Kafka 集群确认,因此它们的操作可以继续进行而不会出现任何中断。

向主题发布消息:
  • 主题规范:品牌发布消息时,生产者负责设置主题,数据将在主题中存储和处理。
  • 记录格式:消息的结构为键、值及其各自的元数据。换句话说,键是标识符,值是消息内容,元数据是附加在记录上的信息。

// Java 中的 Kafka Producer 示例
Properties props = new Properties(); 
props.put("bootstrap.servers", "localhost:9092"); 
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); 
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); 

KafkaProducer<String, String> 生产者 = new KafkaProducer<>(props); 

// 向“example-topic”主题发送消息
ProducerRecord<String, String> record = new ProducerRecord<>("example-topic", "key", "Hello, Kafka!"); 
producer.send(record);

// Closing the producer
producer.close();


消费者 – 处理大量数据
消费者在Kafka中的角色:

  • 数据消费:通过订阅,消费者处理Kafka中生产者通道交换的数据,成为Kafka生态系统的关键角色。
  • 并行处理:消费者可以通过利用消费者网络同时进行系统化,从而在使用目录或数据库的相同基础上实现快速且详细的处理。

订阅主题:
  • 主题订阅:与广播模型相反,消费者订阅感兴趣的特定主题,并且只会将其实际目的所需的数据流接收到其终端系统中。
  • 消费者组动态:多个订阅者可以创建一个联合消费者组来共同接收主题,而不受其他人的干扰。
  • 并行处理的消费者组: 并行处理的消费者组:
  • 组协调:消费者组负责并发方面,并确保消息一次仅由一个而不是所有消费者处理。
  • 并行扩展:消费者群体并行扩展的能力会对质量产生影响,使更多的消费者能够加入并提高处理能力。

维持消费者抵消:
  • 偏移跟踪:消息偏移是消费者记录本身,现有偏移表明每个分区上最后一条消息的位置。
  • 容错:跟踪偏移量将使消费者能够及时了解最后消费的消息,因此如果处理失败,他们可以从离开的地方继续处理。该选项是容错的。

// Java 中的 Kafka Consumer 示例
Properties props = new Properties(); 
props.put("bootstrap.servers", "localhost:9092"); 
props.put("group.id", "example-group"); 
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); 
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); 

KafkaConsumer<String, String> Consumer = new KafkaConsumer<>(props); 

// 订阅“example-topic”主题
consumer.subscribe(Collections.singletonList("example-topic")); 

// 轮询消息
while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
    for (ConsumerRecord<String, String> record : records) {
        // Process the received message
        System.out.printf("Received message: key=%s, value=%s%n", record.key(), record.value());
    }
}


在 Kafka 集群中实现可扩展性和容错性
Apache Kafka 的成功在于其水平扩展和保持容错能力。
通过数据分区实现可扩展性:

  • 并行处理:数据分区是跨多个代理对消息进行并行数据处理的有效工具,因此也增强了系统的可扩展性。
  • 负载平衡:通过分区进行流量控制,平衡处理器之间的工作负载,从而实现资源的最佳利用并避免系统瓶颈。

// Creating a topic with three partitions
AdminClient adminClient = AdminClient.create(props);
NewTopic newTopic = new NewTopic("example-topic", 3, (short) 1);
adminClient.createTopics(Collections.singletonList(newTopic));

通过复制确保容错:

  • 数据持久性:复制的工作方式类似于修复津贴,每个副本都保留多个分区。
  • 连续运行:如果一组复制代理中的一个代理发生冗余性能故障,具有冗余数据的其他代理将不自觉地开始工作和链接交换以提供无缝服务。

从节点故障中无缝恢复的策略:
  • 副本追赶:如果代理根据其恢复策略发生故障,领导节点将与其副本联系,以确保后者符合其当前状态。
  • 动态重新分配:Zookeeper 或其他机制在可用代理上重新分配故障分区。分区以可互换的方式分配给可用的代理,这有助于快速恢复操作。

结论
总之,Apache Kafka的集群架构可以被认为是一个复杂的生态系统,允许构建强大且可扩展的数据管道。从代理、主题和分区等核心组件,到使 Kafka 能够高效处理实时数据的生产者和消费者的动态工作流程,每一个部分都发挥着重要作用。

随着 Kafka 快速发展并适应新版本和最佳实践,正在研究实时数据处理问题的工程师和架构师需要考虑到这一点。通过对 Kafka 集群内的技术细节的深刻理解,您可以释放这个令人难以置信的分布式流平台的全部功能,创建不仅可靠而且能够承受当今数据密集型应用程序日益复杂的动态的数据管道。