文章

Kafka 入门指南

Kafka 介绍

Apache Kafka 是一个开源的分布式事件流处理平台,最初由 LinkedIn 开发,并在 2011 年开源,现由 Apache 软件基金会维护。Kafka 的设计目标是 高吞吐量、低延迟、可扩展、高可用性,适用于实时数据流处理和大规模数据集成。

Kafka相比于传统的消息中间件有三个角色:

  1. 消息系统:Kafka 是高性能的消息队列,单机吞吐量可到达百万级别。同时有主题/分区,集群,多副本,回溯消费,消费组等功能。
  2. 数据存储系统:通过参数配置,Kafka可以永久存储消息。
  3. 流式处理平台:Kafka不仅为每个流行的流处理框架提供了可靠的数据源,还提供了一个完整的流式处理类库,比如窗口,连接,变换,聚合等各类操作。

基础概念

一个典型的 Kafka 体系架构包括若干 producer、若干 Broker、若干 consumer,以及一个 zookeeper 集群,如下图所示,其中 zookeeper 负责集群元数据的管理和控制器的选举等操作。Producer 将消息发送给 Broker,Broker 负责将消息存储到磁盘中,而 Consumer 负责从 Broker 中订阅并消费消息。

在 Kafka 体系架构中,主要有以下三个角色:

  1. Producer:生产者负责将数据写入 Kafka 的 主题(Topic)。 数据通常是以消息的形式发送的,每条消息包含一个键和值。生产者可以决定如何将数据分配到不同的分区中,通常使用轮询或哈希分配策略。
  2. Consumer:消费者从 Kafka 中读取数据。消费者属于一个消费者组,同一个组内的消费者会共同消费一个主题的分区。每个分区只能被消费者组中的一个消费者读取,不同的消费者组可以独立读取同一个分区的数据。
  3. Broker:Kafka 的每个节点称为 Broker,它是 Kafka 集群的组成部分。每个 Broker 维护多个分区,并负责存储这些分区中的消息数据。Kafka 集群通常由多个 Broker 组成,可以水平扩展。

在 Kafka 中还有两个特别重要的概念,主题(Topic)与分区(Partition):

  • Topic:Kafka 中的消息以主题为单位进行分类,生产者负责将消息发送到特定的主题,而消费者会订阅主题并进行消费。
  • Partition:主题是一个逻辑上的概念,它还可以细分为多个分区,一个分区只属于一个主题。同一个主题下的不同分区包含的消息是不同的,分区在物理层面可以看作是一个可追加的日志文件,消息在被追加到分区日志文件的时候会分配一个特定的偏移量(offset)。offset 时消息在分区中的唯一标识,Kafka 通过它来保证消息在分区中的顺序性。通过增加分区的数量可以实现水平扩展。

同时,Kafka 还提供了分区的副本机制 来保证高可用性。同一个分区的不同副本中保存相同的消息,副本采用“一主多从”结构,其中 Leader 副本负责处理读写请求,follower 副本只负责与 leader 副本保持消息同步。副本分布在不同的 Broker 上,当 leader 副本出现故障时,从 follower 副本中重新选举新的 leader 副本对外提供服务。

ISR(In-Sync Replicas,同步副本集合)

为保证高可用性和一致性,Kafka 还使用了 ISR 机制,它指的是那些与 Leader 副本保持同步的所有副本集合。具体来说,它们包含了那些:

  1. 成功复制了最近已提交的消息的副本。
  2. 与 Leader 副本的 LEO(Log End Offset)差距在允许范围内的副本。

这些副本通常被认为是“健康的”,因为它们能够快速地接替 Leader 角色,如果现有 Leader 发生故障时,Kafka 会从 ISR 中选举新的 Leader。

ISR 的作用:

  1. 数据一致性:只有 ISR 中的副本被认为是可靠的,能够保证消息在 Kafka 中不丢失。
  2. Leader 切换:当现有 Leader 发生故障时,Kafka 会从 ISR 中选取新的 Leader。
  3. ACK 确认机制:Kafka 的 acks=all 配置要求消息写入 ISR 中的所有副本才能确认写入成功,从而保证更高的一致性。

使用 Docker Compose 文件部署 Kafka 集群

以下是一个 docker-compose.yml 文件,它在单台服务器上部署一个 3 个 Kafka 节点的集群,同时使用 Kafka 内置的 KRaft 模式(无需 Zookeeper)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
version: '3.8'

services:
  kafka1:
    image: bitnami/kafka:latest
    container_name: kafka1
    environment:
      - KAFKA_KRAFT_CLUSTER_ID=80adc4a7
      - KAFKA_CFG_NODE_ID=1
      - KAFKA_BROKER_ID=1
      - KAFKA_CFG_PROCESS_ROLES=broker,controller
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
      - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
      - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka1:9092
      - KAFKA_CFG_LOG_DIRS=/tmp/kafka-logs
      - KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
    ports:
      - 9092:9092
    networks:
      - kafka-network

  kafka2:
    image: bitnami/kafka:latest
    container_name: kafka2
    environment:
      - KAFKA_CFG_NODE_ID=2
      - KAFKA_KRAFT_CLUSTER_ID=80adc4a7
      - KAFKA_BROKER_ID=2
      - KAFKA_CFG_PROCESS_ROLES=broker,controller
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
      - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
      - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka2:9092
      - KAFKA_CFG_LOG_DIRS=/tmp/kafka-logs
      - KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
    ports:
      - 9093:9092
    networks:
      - kafka-network

  kafka3:
    image: bitnami/kafka:latest
    container_name: kafka3
    environment:
      - KAFKA_CFG_NODE_ID=3
      - KAFKA_KRAFT_CLUSTER_ID=80adc4a7
      - KAFKA_BROKER_ID=3
      - KAFKA_CFG_PROCESS_ROLES=broker,controller
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
      - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
      - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka3:9092
      - KAFKA_CFG_LOG_DIRS=/tmp/kafka-logs
      - KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
    ports:
      - 9094:9092
    networks:
      - kafka-network

networks:
  kafka-network:
    driver: bridge
  1. 解释:
  • Kafka 镜像:使用 bitnami/kafka 镜像,它支持 KRaft 模式。
  • KAFKA_BROKER_ID:每个 Kafka 节点的唯一 ID。
  • KAFKA_CFG_CONTROLLER_QUORUM_VOTERS:指定控制器的投票者,每个节点都充当 Broker 和 Controller 角色。
  • KAFKA_CFG_LISTENERS & ADVERTISED_LISTENERS:定义 Kafka 的监听和广告地址。
  • Replication Factor:在集群中使用 3 个副本以确保高可用性。
    1. 启动 Kafka 集群,在 docker-compose.yml 文件所在目录中,执行以下命令:
      1
      
      docker-compose up -d
      

      这将启动 3 个 Kafka 节点。你可以通过 docker ps 查看容器状态。

本文由作者按照 CC BY 4.0 进行授权