1. Kafka 基础概念:Topic、Partition、Broker、Producer、Consumer、Consumer Group 的定义与关系

Kafka 是一个分布式、分区化、多副本的发布-订阅消息系统。理解其核心概念是掌握消费者组与分区分配机制的前提。本节将逐一拆解 Topic、Partition、Broker、Producer、Consumer 和 Consumer Group 的定义,并阐明它们之间的协作关系。

1.1 核心概念定义

概念 定义 关键特征
Topic(主题) 消息的逻辑分类名称,是生产者发送消息和消费者订阅消息的基本单位。 一个 Topic 可被多个 Consumer Group 独立消费;Topic 内的消息不直接排序。
Partition(分区) Topic 的物理分片,每个 Partition 是一个有序、不可变的消息日志(append-only log)。 Partition 内消息按 offset 严格排序;Partition 是 Kafka 并行度的最小单位。
Broker(代理节点) Kafka 集群中的单个服务器实例,负责存储 Partition 数据、处理读写请求。 一个 Broker 可管理多个 Partition;集群通过 Broker 数量实现水平扩展。
Producer(生产者) 向指定 Topic 发布消息的客户端应用程序。 可指定分区策略(如轮询、key 哈希、自定义分区器)。
Consumer(消费者) 从 Topic 拉取消息的客户端应用程序,通常隶属于一个 Consumer Group。 每个 Consumer 负责处理分配给它的 Partition 中的消息。
Consumer Group(消费者组) 一组 Consumer 实例的逻辑集合,共同消费一个或多个 Topic 的全部消息。 组内 Partition 分配策略由 Group Coordinator 协调;组内 Consumer 数量不应超过总 Partition 数。

1.2 概念关系与数据流

下图展示了从 Producer 到 Consumer Group 的完整数据流转路径,以及各核心组件之间的层级关系。

Kafka 核心概念关系图 Kafka 核心概念关系与数据流 Producer Topic 物理分片 Partition 集合 P-0 P-1 P-2 每个 Partition 是有序日志 Broker 1 Broker 2 Broker 3 Consumer Group C-0 C-1 C-2 关键关系 • 1 Topic → N Partition • 1 Partition → 1 Broker(主) • 1 Partition → 1 Consumer(组内) • N Consumer → 1 Consumer Group

1.3 核心关系详解

1.3.1 Topic 与 Partition

  • 一对多关系:一个 Topic 被划分为多个 Partition,Partition 数量在创建 Topic 时指定,后续可扩容(但不可缩容)。
  • 有序性边界:消息的有序性仅在 Partition 内部保证,跨 Partition 的消息不保证全局顺序。
  • 物理存储:每个 Partition 对应 Broker 文件系统上的一个目录,目录内包含多个 segment 文件。

1.3.2 Partition 与 Broker

  • 分布存储:Partition 分布在集群的不同 Broker 上,实现负载均衡。
  • 主从复制:每个 Partition 有 1 个 Leader 和 N 个 Follower;Leader 负责读写,Follower 同步数据。
  • 故障转移:当 Leader Broker 宕机时,Controller 从 ISR(In-Sync Replicas)中选举新的 Leader。

1.3.3 Consumer 与 Partition

  • 独占消费:在同一个 Consumer Group 内,一个 Partition 最多只能被一个 Consumer 实例消费。
  • 并行度上限:Group 内最大并行消费能力等于 Topic 的总 Partition 数。
  • 分配策略:Kafka 提供 RangeAssignor、RoundRobinAssignor、StickyAssignor 等策略,也支持自定义。

💡 关键约束:如果 Consumer Group 内的 Consumer 数量超过 Topic 的 Partition 总数,多余的 Consumer 将处于空闲状态(不接收任何消息)。这是设计消费者组规模时必须避免的陷阱。

1.4 消费者组边界特性

Consumer Group 是 Kafka 实现点对点和发布-订阅两种消息模型的核心机制:

特性 说明 示例场景
组内隔离 同一 Group 内的 Consumer 共同消费 Topic 的全部消息,每条消息只被组内一个 Consumer 处理。 订单处理服务集群(避免重复处理)
组间独立 不同 Group 可以独立消费同一个 Topic,每个 Group 都有自己的消费偏移量(offset)。 订单数据同时被实时计算和数仓归档
动态重平衡 当 Group 内 Consumer 加入、离开或 Topic 分区数变化时,触发 Rebalance 重新分配 Partition。 服务扩缩容时自动调整消费负载
偏移量管理 每个 Consumer 定期提交已消费的 offset 到 Kafka 内部 Topic(__consumer_offsets)。 宕机恢复后从上次提交的 offset 继续消费

1.5 生产者与消费者的 Go 语言快速示例

以下代码展示了 Go 语言中使用 segmentio/kafka-go 库创建 Producer 和 Consumer 的基本模式:

// Producer:向 Topic "orders" 发送消息
package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/segmentio/kafka-go"
)

func main() {
    writer := &kafka.Writer{
        Addr:     kafka.TCP("localhost:9092"),
        Topic:    "orders",
        Balancer: &kafka.Hash{},
        BatchTimeout: 10 * time.Millisecond,
    }
    defer writer.Close()

    err := writer.WriteMessages(context.Background(),
        kafka.Message{
            Key:   []byte("user_123"),
            Value: []byte(`{"order_id":"ord_001","amount":99.9}`),
        },
    )
    if err != nil {
        log.Fatal("failed to write message:", err)
    }
    fmt.Println("message sent")
}
// Consumer:从 Consumer Group "order-service" 消费消息
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/segmentio/kafka-go"
)

func main() {
    reader := kafka.NewReader(kafka.ReaderConfig{
        Brokers:   []string{"localhost:9092"},
        Topic:     "orders",
        GroupID:   "order-service",
        MinBytes:  10e3, // 10KB
        MaxBytes:  10e6, // 10MB
    })
    defer reader.Close()

    for {
        msg, err := reader.ReadMessage(context.Background())
        if err != nil {
            log.Fatal("failed to read message:", err)
        }
        fmt.Printf("partition=%d offset=%d key=%s value=%s\n",
            msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
    }
}

📌 实践要点:

  • Producer 的 Balancer 决定消息写入哪个 Partition;kafka.Hash 保证相同 Key 的消息进入同一 Partition。
  • Consumer 的 GroupID 是消费者组的唯一标识;同一 GroupID 的多个 Consumer 实例自动组成一个 Group。
  • 建议在 Go 服务启动时通过环境变量注入 GroupID,便于多环境隔离。

1.6 概念关系总结

下图以分层视角总结 Topic、Partition、Broker、Consumer Group 之间的逻辑与物理关系:

Kafka 分层架构关系图 Kafka 分层架构:逻辑层与物理层 逻辑层(面向客户端) Topic Partition Consumer Group 消息分类 并行分片 消费边界 物理层(集群存储) Broker 集群 Partition 副本 Offset 存储 服务器节点 数据冗余 消费进度

⚠️ 常见误解澄清:

  • 误解一:Topic 是队列。实际上 Topic 是日志结构,消息被追加后不会删除(除非超过保留时间或大小)。
  • 误解二:Consumer Group 内所有 Consumer 必须处理相同的消息。实际上每条消息只被组内一个 Consumer 处理。
  • 误解三:Partition 越多越好。实际上过多的 Partition 会增加 Broker 的元数据开销和 Rebalance 时间,建议根据吞吐量合理设置。