大数据-66 Kafka 分区与副本机制详解:高可用与高性能的核心与实战 副本与分区

143 阅读10分钟

点一下关注吧!!!非常感谢!!持续更新!!!

🚀 AI篇持续更新中!(长期更新)

AI炼丹日志-31- 千呼万唤始出来 GPT-5 发布!“快的模型 + 深度思考模型 + 实时路由”,持续打造实用AI工具指南!📐🤖

💻 Java篇正式开启!(300篇)

目前2025年08月11日更新到: Java-94 深入浅出 MySQL EXPLAIN详解:索引分析与查询优化详解 MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务正在更新!深入浅出助你打牢基础!

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈! 大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

请添加图片描述

章节内容

上一节我们完成了如下的内容: 现实业务中我们会遇到:当Kafka集群中有一个节点宕机了,比如Broker0、Broker1中,Broker1宕机了,此时由于我们配置了副本数为2,Kafka集群正常工作,提供生产和消费能力。 但是当我们修好Broker1之后,恢复宕机之后,发现Leader都是Broker0,不会再平衡到Broker1上,所以我们需要用脚本来让Kafka集群进行自动再平衡。

  • Kafka自动再平衡
  • 新建主题
  • 查看主题
  • 模拟宕机
  • 重启节点
  • 编写JSON
  • 测试运行

在这里插入图片描述

分区(Partition)

Kafka 中的每个主题(Topic)都可以分为多个分区。分区是 Kafka 实现可扩展性和高吞吐量的关键机制,它通过以下方式提升系统性能:

  1. 并行处理能力:分区允许消息被并行处理,不同的分区可以由不同的消费者同时处理,从而提高整体吞吐量。

  2. 数据分布:每个分区可以分布在不同的服务器(Broker)上,实现数据的分布式存储和处理。

  3. 水平扩展:通过增加分区数量,可以线性提升主题的吞吐量。

每个分区可以看作是一个有序的、不可变的消息队列,具有以下核心特性:

  • 消息顺序性保证:消息在分区内严格按写入顺序进行存储,并且每个消息都会分配一个唯一的递增偏移量(Offset)。这种设计保证了同一分区内的消息顺序性,但不同分区之间的消息顺序则无法保证。

  • 持久化存储:分区中的消息会被持久化到磁盘,并可以根据配置的保留策略(retention policy)保留一定时间(如7天)或达到一定大小。

  • 副本机制:每个分区可以有多个副本(Replicas),其中一个作为领导者(Leader)负责处理读写请求,其他作为跟随者(Follower)用于故障转移。

应用场景示例:

  • 电商订单处理系统可以将不同用户的订单分配到不同分区,既保证同一用户订单的顺序处理,又实现系统的水平扩展。
  • 日志收集系统可以按日志来源设备ID进行分区,确保同一设备的日志顺序性。

实际操作中,创建主题时就需要指定分区数量(如bin/kafka-topics.sh --create --topic my_topic --partitions 3),后续虽然可以增加分区数,但需要谨慎操作以避免影响现有消息的键到分区映射。

分区优势

  • 并行处理:通过将主题分为多个分区,Kafka 可以在多台服务器上并行处理消息,从而提高系统的吞吐量。
  • 负载均衡:消费者组中的不同消费者可以消费不同的分区,从而实现负载均衡。
  • 水平扩展:当需要处理更多的消息时,可以通过增加分区来扩展 Kafka 集群的容量。

副本因子(Replication Factor 或者 Replicas)

副本因子是Apache Kafka中一个重要的配置参数,它定义了每个分区在Kafka集群中的副本数量。这个参数决定了数据在集群中的冗余程度和系统的高可用性。

副本的角色与职责

每个分区的副本由以下两种角色组成:

1. 首领副本(Leader)

  • Leader是分区的主要副本,承担着核心的数据处理职责
  • 负责处理所有客户端的读写请求(包括生产者和消费者的请求)
  • 维护ISR(In-Sync Replicas)列表,跟踪哪些Follower处于同步状态
  • 当有新的消息写入时,Leader会将这些消息同步给Follower副本
  • 示例:假设一个分区有3个副本(副本因子为3),其中1个是Leader,2个是Follower

2. 追随者副本(Follower)

  • Follower是Leader的备份副本,主要用于数据冗余和故障恢复
  • 定期从Leader拉取消息保持数据同步(这个过程称为"fetch"操作)
  • 正常情况下不直接处理客户端的任何请求
  • 在Leader失效时,通过Kafka的控制器(Controller)选举机制,其中一个Follower会被提升为新的Leader
  • 示例:在网络分区或节点故障时,Follower可以接管成为Leader,确保服务不中断

副本因子的重要性

合理的副本因子设置需要考虑:

  • 数据可靠性需求(副本越多,数据丢失风险越低)
  • 集群资源开销(每个副本都需要存储空间和网络带宽)
  • 读写性能影响(副本同步会带来一定的延迟)

典型的生产环境配置:

  • 开发环境:副本因子=1(无冗余)
  • 测试环境:副本因子=2(基本冗余)
  • 生产环境:副本因子=3(高可用性配置)

副本同步机制

Kafka使用ISR(In-Sync Replicas)机制来管理副本同步:

  1. Leader维护一个ISR列表,包含所有与Leader保持同步的副本
  2. 只有ISR中的副本才有资格在Leader失效时被选举为新的Leader
  3. 如果Follower长时间未同步(超过replica.lag.time.max.ms参数设置的时间),会被移出ISR列表

这种机制确保了在故障转移时,新选举的Leader拥有最新的数据。

副本因子作用

  • 容错性:副本因子提供了容错能力。当一个节点发生故障时,Kafka 可以通过选举新的 Leader 来保证数据的可用性。
  • 高可用性:即使集群中的部分节点不可用,Kafka 依然能够确保数据的可用性和持久性。
  • 副本因子的选择:副本因子通常设置为 3,这意味着每个分区有 3 个副本。这样即使有一个副本节点宕机,系统仍然能保证数据的安全性和服务的连续性。

工作原理

在 Kafka 中,当一个消息写入到某个分区时,首先会写入到该分区的 Leader 副本中,然后 Leader 会将该消息同步到所有的 Follower 副本。当所有的 Follower 都成功同步后,该消息才被认为是提交成功的(即对消费者可见)。

通过分区和副本因子,Kafka 实现了数据的高可用性和高性能处理能力。在实际应用中,合理配置分区和副本因子对于 Kafka 集群的性能和稳定性至关重要。

修改分区副本的详细操作指南

业务背景与需求场景

在实际业务和项目开发过程中,我们经常会遇到需要调整Kafka主题(Topic)副本因子(replication factor)的情况。以下是几种典型场景:

  1. 初始配置不足:新创建主题时可能低估了数据重要性,设置过小的副本因子(如1),随着业务发展需要增加冗余保障

  2. 集群扩容:当Kafka集群规模扩大后,需要将原有主题的副本分布到新增节点上,充分利用集群资源

  3. 故障容灾:发现某些主题数据丢失风险较高,需要提高容错能力

  4. 性能优化:通过增加副本改善消费者读取性能,特别是跨地域部署场景

技术实现方案

由于生产环境中主题通常承载着关键业务数据,简单的删除重建方式不可行,因此需要通过Kafka提供的动态修改机制来完成:

详细操作步骤

  1. 创建副本分配计划文件

    {
      "version": 1,
      "partitions": [
        {"topic": "your_topic", "partition": 0, "replicas": [0, 1, 2]},
        {"topic": "your_topic", "partition": 1, "replicas": [0, 2, 3]},
        {"topic": "your_topic", "partition": 2, "replicas": [1, 2, 3]}
      ]
    }
    

    其中replicas数组应包含新的副本列表,包含原有副本加上新增副本

  2. 执行副本重新分配

    bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 \
    --reassignment-json-file increase-replication-factor.json \
    --execute
    
  3. 验证分配进度

    bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 \
    --reassignment-json-file increase-replication-factor.json \
    --verify
    

注意事项

  1. 性能影响:副本重分配会引发大量数据传输,建议在业务低峰期操作

  2. 监控指标:操作期间需密切关注以下指标:

    • 网络吞吐量
    • 磁盘IO使用率
    • 集群负载均衡情况
  3. 回滚方案:提前准备回滚计划,包括:

    • 原有副本分配配置备份
    • 快速终止重分配的操作命令
  4. 客户端适配:某些客户端可能需要重启才能感知新的副本分布

最佳实践建议

  1. 预生产验证:在测试环境充分验证重分配方案

  2. 分批次操作:对于大型集群,建议分批次处理不同主题

  3. 文档记录:详细记录变更前后的配置和验证结果

  4. 自动化工具:考虑使用Ansible、Chef等工具实现标准化操作流程

通过以上方法,可以在不影响业务连续性的前提下,安全地完成Kafka主题副本因子的动态调整。

背景情况

假设我们有两个KafkaBroker分别为:Broker0、Broker1

  • 当我们创建Topic有2个分区,并且replication-factor为1,基本一个Broker一个分区。
  • 当一个分区宕机了,该Topic就无法使用了,因为两个分区中只有一个可以使用
  • 当我们创建的Topic有3个分区时,replication-factor为2时,可能分区数据分布情况是:[broker0,partition0,partition1,partition2] 和 [broker1,partition1,partition0,partition2]
  • 每个分区有一个副本,当其中一个Broker宕机了,Kafka集群还能完整的凑出该Topic的两个分区,例如当Broker0宕机了,可以通过Broker1组合出Topic的两个分区。

启动服务

确保你有两台节点是可以正常使用的: 我这里是h121和h122

kafka-server-start.sh /opt/servers/kafka_2.12-2.7.2/config/server.properties

h121

在这里插入图片描述

h122

在这里插入图片描述

创建主题

kafka-topics.sh --zookeeper h121.wzk.icu:2181 --create --topic topic_test_02 --partitions 3 --replication-factor 1

运行结果如下图: 在这里插入图片描述

查看主题

kafka-topics.sh --zookeeper h121.wzk.icu:2181 --describe --topic topic_test_02

运行结果如下图: 在这里插入图片描述 可以看到跟我们的上一个实验的开头分配情况是一致的。

修改副本因子(不允许)

尝试修改

# 刚才 --create的时候 --replication-factor是1
kafka-topics.sh --zookeeper h121.wzk.icu:2181 --alter --topic topic_test_02 --replication-factor 2

我们可以观察到,是不允许我们这样操作的: 在这里插入图片描述

那如果我们业务上要求我们修改副本因子,我们该怎么办呢? 下面提供一个可行的方案。

修改副本因子

编写JSON

所以我们需要借助 kafka-reassign-partitions.sh 新建一个文件,这里的JSON在replicase里写入了多个:

vim topic_test_02_increment-replication-factor.json

{
  "versions": "1",
  "partitions": [
    {
      "topic": "topic_test_02", "partition": 0, "replicas": [0,1]
    }, 
    {
      "topic": "topic_test_02", "partition": 1, "replicas": [0,1]
    },
    {
      "topic": "topic_test_02", "partition": 2, "replicas": [1,0]
    }
  ]
}

我们写入的内容如下: 在这里插入图片描述

执行JSON

kafka-reassign-partitions.sh --zookeeper h121.wzk.icu:2181 --reassignment-json-file topic_test_02_increment-replication-factor.json --execute

观察执行的结果如下: 在这里插入图片描述

查看结果

kafka-topics.sh --zookeeper h121.wzk.icu:2181 --describe --topic topic_test_02

执行的结果如下图所示: 在这里插入图片描述 可以看到,我们的副本数已经是 01、01、10了,此时就算 h121 或者 h122 中有一台节点挂掉了,我们也可以继续进行消费!