3. Topic与Partition

Topic 是 Kafka 中消息的逻辑分类,而 Partition 是 Kafka 实现水平扩展与高可用的核心单元。理解 Topic 的创建方式、Partition 的分区策略、副本机制以及 Leader 选举流程,是掌握 Kafka 架构的基石。本章将深入剖析这些核心概念,并结合微服务链路中的实际场景进行讲解。

3.1 Topic 的创建与管理

Topic 的创建方式分为自动创建与手动创建。在生产环境中,建议使用手动创建以精确控制分区数与副本因子。

3.1.1 创建方式对比

创建方式 触发条件 适用场景 注意事项
自动创建 生产者或消费者向不存在的 Topic 发送/拉取消息 开发测试环境、快速验证 可能因配置不当导致分区数或副本数不符合预期
手动创建 通过 kafka-topics.sh 脚本或 Admin API 生产环境、微服务正式链路 可精确指定分区数、副本因子及配置参数

3.1.2 手动创建示例

# 创建一个名为 "order-events" 的 Topic,6 个分区,3 个副本
bin/kafka-topics.sh --create \
  --bootstrap-server localhost:9092 \
  --replication-factor 3 \
  --partitions 6 \
  --topic order-events \
  --config cleanup.policy=delete \
  --config retention.ms=604800000
微服务实践建议: 在微服务链路中,建议为每个核心业务事件(如订单创建、支付成功)创建独立的 Topic。分区数建议设置为 Broker 数量的整数倍,以便均匀分布负载。

3.2 Partition 分区策略

分区策略决定了消息被发送到哪个 Partition。合理的分区策略可以保证数据均匀分布,并支持消息的顺序性需求。

3.2.1 常见分区策略

  • 轮询策略(Round-Robin): 默认策略,消息依次发送到每个 Partition,负载最均匀。
  • 哈希策略(Hash): 对消息 Key 进行哈希计算,相同 Key 的消息总是进入同一 Partition,保证局部顺序。
  • 粘性分区策略(Sticky Partitioner): Kafka 2.4+ 默认,减少网络开销,提高吞吐量。
  • 自定义分区策略: 实现 Partitioner 接口,满足业务特殊路由需求。

3.2.2 分区策略选择矩阵

业务需求 推荐策略 说明
全局顺序 单分区 Topic 所有消息进入同一 Partition,牺牲并行度
局部顺序(按 Key) 哈希策略 相同订单 ID 的消息进入同一 Partition
高吞吐、无顺序要求 轮询 / 粘性分区 均匀分布,最大化并行处理能力
按业务字段路由 自定义分区器 例如按用户地域、事件类型路由

3.3 副本机制(Replication)

副本机制是 Kafka 高可用的核心保障。每个 Partition 可以有多个副本,分布在不同的 Broker 上。

3.3.1 副本角色

  • Leader: 每个 Partition 有且仅有一个 Leader,负责处理所有读写请求。
  • Follower: 被动同步 Leader 的数据,不对外提供服务。当 Leader 故障时,Follower 可被选举为新的 Leader。
  • ISR(In-Sync Replicas): 与 Leader 保持同步的副本集合。只有 ISR 中的副本才有资格成为 Leader。

3.3.2 副本同步机制

Leader 收到消息后,Follower 会主动拉取(Pull)数据进行同步。只有当消息被 ISR 中所有副本确认后,才被认为“已提交”。

关键参数:
  • min.insync.replicas:最小 ISR 副本数,控制写入可用性。建议设置为 2。
  • acks:生产者确认级别。acks=all 表示等待 ISR 全部确认,保证数据不丢失。
Partition 副本同步与 ISR 机制 Broker 1 Partition-0 Leader LEO: 100 Broker 2 Partition-0 Follower LEO: 100 (ISR) Broker 3 Partition-0 Follower LEO: 100 (ISR) ISR 同步说明 • Leader 负责所有读写请求,Follower 从 Leader 拉取数据。 • ISR 中的 Follower 与 Leader 保持完全同步(LEO 相同)。 • 当 Leader 故障时,Controller 从 ISR 中选举新的 Leader。 • 若 Follower 落后太多或崩溃,会被踢出 ISR,避免影响写入性能。 • 参数 replica.lag.time.max.ms 控制 Follower 最大允许落后时间。

3.4 分区 Leader 选举

当 Partition 的 Leader 发生故障时,Kafka Controller 会负责从 ISR 中选举一个新的 Leader。选举过程对客户端透明,但会影响短暂的可用性。

3.4.1 选举触发条件

  • Leader 所在的 Broker 宕机。
  • Leader 发生网络分区,与 Controller 心跳超时。
  • Leader 因异常退出(如 OOM、磁盘故障)。

3.4.2 选举流程

  1. 检测故障: Controller 通过 ZooKeeper 或 KRaft 心跳检测到 Leader 不可用。
  2. 获取 ISR 列表: Controller 从元数据中获取该 Partition 的 ISR 集合。
  3. 选举新 Leader: 从 ISR 中选择第一个副本作为新 Leader(按副本 ID 排序)。
  4. 更新元数据: Controller 将新的 Leader 信息广播给所有 Broker 和客户端。
  5. 恢复服务: 新 Leader 开始处理读写请求,Follower 开始从新 Leader 同步数据。
注意: 如果 ISR 为空(所有副本都不可用),Kafka 会等待第一个恢复的副本成为 Leader,但该副本可能丢失部分数据(unclean leader election)。生产环境建议关闭 unclean leader election(unclean.leader.election.enable=false),以数据一致性优先。
Partition Leader 选举流程 ① Leader 故障 Broker 宕机 / 心跳超时 ② 检测故障 Controller 感知 ③ 获取 ISR 读取元数据 ④ 选举 选 ISR 首位 ⑤ 更新元数据 广播新 Leader 信息 ⑥ 恢复服务 新 Leader 处理读写 选举关键点 • 选举由 Controller 负责,Controller 是集群的“大脑”。 • 优先从 ISR 中选举,保证数据不丢失。 • 若 ISR 为空且 unclean.leader.election.enable=true, 可能选举落后副本,导致数据丢失。 • 选举期间,该 Partition 不可用(通常毫秒级)。 • 客户端通过 Metadata 请求感知新 Leader 地址。

3.5 微服务链路中的最佳实践

微服务链路配置建议:
  • 分区数规划: 根据业务流量预估,建议分区数 = Broker 数 × 2~4,便于后续扩展。
  • 副本因子: 生产环境至少 3 副本,容忍 1 个 Broker 故障;重要链路建议 3 副本 + 2 个机架。
  • 分区策略: 需要保证事件顺序(如订单状态变更)时,使用订单 ID 作为 Key 进行哈希分区。
  • 监控指标: 关注 UnderReplicatedPartitions、LeaderElectionRateAndTimeMs 等指标,及时发现副本同步和选举异常。