Kafka的分区和副本机制

举报
tea_year 发表于 2025/04/29 15:19:36 2025/04/29
【摘要】 Apache Kafka 是一个分布式流处理平台,广泛应用于高吞吐量、低延迟的消息传递场景。其核心设计理念之一是通过 分区(Partition) 和 副本(Replica) 机制实现 水平扩展 和 高可用性。分区(Partition):Kafka 的 Topic 可以划分为多个 Partition,每个 Partition 是一个有序的、不可变的消息序列,支持并行生产和消费,从而提升吞吐量。...

Apache Kafka 是一个分布式流处理平台,广泛应用于高吞吐量、低延迟的消息传递场景。其核心设计理念之一是通过 分区(Partition)  副本(Replica) 机制实现 水平扩展  高可用性

  • 分区(Partition):Kafka 的 Topic 可以划分为多个 Partition,每个 Partition 是一个有序的、不可变的消息序列,支持并行生产和消费,从而提升吞吐量。
  • 副本(Replica):每个 Partition 可以有多个副本(Replica),分布在不同的 Broker 上,确保数据冗余和故障恢复能力。

2. 核心挑战

  • 如何提高吞吐量? → 通过 分区并行化 实现多生产者/消费者并发处理。
  • 如何保证数据可靠性? → 通过 副本机制 防止单点故障,确保数据不丢失。
  • 如何平衡性能与一致性? → 通过 ISR(In-Sync Replicas) 机制在性能和数据一致性之间权衡。

3. 技术价值

Kafka 的分区和副本机制使其成为 大规模分布式系统 的核心组件,适用于日志收集、实时流处理、事件驱动架构等场景。

一、生产者分区写入策略

生产者写入消息到topic,Kafka将依据不同的策略将数据分配到不同的分区中

  1. 轮询分区策略

  2. 随机分区策略

  3. 按key分区分配策略

  4. 自定义分区策略

1.1 轮询策略

image-20201228221829146.png

  • 默认的策略,也是使用最多的策略,可以最大限度保证所有消息平均分配到一个分区

  • 如果在生产消息时,key为null,则使用轮询算法均衡地分配分区

1.2 随机策略(不用)

随机策略,每次都随机地将消息分配到每个分区。在较早的版本,默认的分区策略就是随机策略,也是为了将消息均衡地写入到每个分区。但后续轮询策略表现更佳,所以基本上很少会使用随机策略。

image-20201228221949824.png

1.3 按key分配策略

按key分配策略,有可能会出现「数据倾斜」,例如:某个key包含了大量的数据,因为key值一样,所有的数据将都分配到一个分区中,造成该分区的消息数量远大于其他的分区。key.hashCode() % 分区数量。

1.4 乱序问题

轮询策略、随机策略都会导致一个问题,生产到Kafka中的数据是乱序存储的。而按key分区可以一定程度上实现数据有序存储——也就是局部有序,但这又可能会导致数据倾斜,所以在实际生产环境中要结合实际情况来做取舍。

1.5 自定义分区策略

image-20201228222143177.png

实现步骤:

  1. 创建自定义分区器

public class KeyWithRandomPartitioner implements Partitioner {
​
    private Random r;
​
    @Override
    public void configure(Map<String, ?> configs) {
        r = new Random();
    }
​
    @Override
    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
        // cluster.partitionCountForTopic 表示获取指定topic的分区数量
        return r.nextInt(1000) % cluster.partitionCountForTopic(topic);
    }
​
    @Override
    public void close() {
    }
}
  1. 在Kafka生产者配置中,自定使用自定义分区器的类名

props.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, KeyWithRandomPartitioner.class.getName());

二、消费者组Rebalance机制

2.1 Rebalance再均衡

Kafka中的Rebalance称之为再均衡,是Kafka中确保Consumer group下所有的consumer如何达成一致,分配订阅的topic的每个分区的机制。

Rebalance触发的时机有:

  1. 消费者组中consumer的个数发生变化。例如:有新的consumer加入到消费者组,或者是某个consumer停止了。

image-20201228222450421.png

  1. 订阅的topic个数发生变化

消费者可以订阅多个主题,假设当前的消费者组订阅了三个主题,但有一个主题突然被删除了,此时也需要发生再均衡。

image-20201228222549887.png

  1. 订阅的topic分区数发生变化

image-20201228233951112.png


分区再均衡:

因为群组里的消费者共同读取主题的分区,所以当一个消费者被关闭或者发生崩溃时,原本又它读取的分区将由群组里的其他消费者读取。同时 在主题发生变化时,比如添加了新的分区,也会发生分区与消费者的重新分配,分区的所有权从一个消费者转移到另一个消费者,这样的行为成为再均衡。正是因为再均衡,所以消费者群组才能保证高可用性和伸缩性。

消费者通过向群组协调器所在的broker发送心跳检测来维护他们和群组的从属关系以及它们对分区的所有权。只要消费者以正常的时间间隔发送心跳,就被认为是活跃的,说明它还在读取分区里的数据。消费者会在轮询消息和提交偏移量时发送心跳,如果消费者停止发送心跳的时间足够长,会话就会过期,群组协调器会认为它死亡了,就会触发再均衡。

2.2 Rebalance的不良影响

  • 发生Rebalance时,consumer group下的所有consumer都会协调在一起共同参与,Kafka使用分配策略尽可能达到最公平的分配

  • Rebalance过程会对consumer group产生非常严重的影响,Rebalance的过程中所有的消费者都将停止工作,直到Rebalance完成

三、消费者分区分配策略

3.1 Range范围分配策略

Range范围分配策略是Kafka默认的分配策略,它可以确保每个消费者消费的分区数量是均衡的。

注意:Rangle范围分配策略是针对每个Topic的。

配置

配置消费者的 partition.assignment.strategy 为 org.apache.kafka.clients.consumer.RangeAssignor。

算法公式

n = 分区数量 / 消费者数量

m = 分区数量 % 消费者数量

前m个消费者消费n+1个

剩余消费者消费n个

image-20201228234355036.png

3.2 RoundRobin轮询策略

RoundRobinAssignor轮询策略是将消费组内所有消费者以及消费者所订阅的所有topic的partition按照字典序排序(topic和分区的hashcode进行排序),然后通过轮询方式逐个将分区以此分配给每个消费者。

配置

配置消费者的partition.assignment.strategy为org.apache.kafka.clients.consumer.RoundRobinAssignor。

image-20201228234436122.png

3.3 Stricky粘性分配策略

从Kafka 0.11.x开始,引入此类分配策略。主要目的:

    1. 分区分配尽可能均匀

    1. 在发生rebalance的时候,分区的分配尽可能与上一次分配保持相同

没有发生rebalance时,Striky粘性分配策略和RoundRobin分配策略类似。

image-20201228234743483.png

上面如果consumer2崩溃了,此时需要进行rebalance。如果是Range分配和轮询分配都会重新进行分配,例如:

image-20201228234923570.png

通过上图,我们发现,consumer0和consumer1原来消费的分区大多发生了改变。接下来我们再来看下粘性分配策略。

image-20201228235002466.png

我们发现,Striky粘性分配策略,保留rebalance之前的分配结果。这样,只是将原先consumer2负责的两个分区再均匀分配给consumer0、consumer1。这样可以明显减少系统资源的浪费,例如:之前consumer0、consumer1之前正在消费某几个分区,但由于rebalance发生,导致consumer0、consumer1需要重新消费之前正在处理的分区,导致不必要的系统开销。(例如:某个事务正在进行就必须要取消了)

四、 副本机制

副本的目的就是冗余备份,当某个Broker上的分区数据丢失时,依然可以保障数据可用。因为在其他的Broker上的副本是可用的。

4.1 producer的ACKs参数

对副本关系较大的就是,producer配置的acks参数了,acks参数表示当生产者生产消息的时候,写入到副本的要求严格程度。它决定了生产者如何在性能和可靠性之间做取舍。

配置:

Properties props = new Properties();
props.put("bootstrap.servers", "node1:9092");
props.put("acks", "all");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

4.2 acks配置为0

image-20201228235451359.png

ACK为0,基准测试:

bin/kafka-producer-perf-test.sh --topic benchmark --num-records 5000000 --throughput -1 --record-size 1000 --producer-props bootstrap.servers=node1:9092,node2:9092,node3:9092 acks=0

4.3 acks配置为1

image-20201228235755100.png

当生产者的ACK配置为1时,生产者会等待leader副本确认接收后,才会发送下一条数据,性能中等。

ACK为1,基准测试:

bin/kafka-producer-perf-test.sh --topic benchmark --num-records 5000000 --throughput -1 --record-size 1000 --producer-props bootstrap.servers=node1:9092,node2:9092,node3:9092 acks=1

测试结果:

指标 单分区单副本(ack=0) 单分区单副本(ack=1)
吞吐量 165875.991109 records/sec每秒16.5W条记录 93092.533979 records/sec 每秒9.3W条记录
吞吐速率 158.19 MB/sec每秒约160MB数据 88.78 MB/sec每秒约89MB数据
平均延迟时间 192.43 ms avg latency 346.62 ms avg latency
最大延迟时间 670.00 ms max latency 1003.00 ms max latency

4.4 acks配置为-1或者all

image-20201229000039787.png

bin/kafka-producer-perf-test.sh --topic benchmark --num-records 5000000 --throughput -1 --record-size 1000 --producer-props bootstrap.servers=node1:9092,node2:9092,node3:9092 acks=all
指标 单分区单副本(ack=0) 单分区单副本(ack=1) 单分区单副本(ack=-1/all)
吞吐量 165875.991109/s每秒16.5W条记录 93092.533979/s 每秒9.3W条记录 73586.766156 /s每秒7.3W调记录
吞吐速率 158.19 MB/sec 88.78 MB/sec 70.18 MB
平均延迟时间 192.43 ms 346.62 ms 438.77 ms
最大延迟时间 670.00 ms 1003.00 ms 1884.00 ms

发送确认:

kafka在生产者上有一个可选的参数:acks,该参数指定了必须要有多少个分区副本收到消息,生产者才会认为消息写入成功。

  • acks:0 消息发送出去就认为已经成功了,不会等待任何来自服务器的响应。性能最好,但有可能丢失数据。

  • acks:1 只有集群的leader节点收到消息,生产者就会收到一个来自服务器的成功响应。

  • acks:-1 或 all 只有当所有分区副本都收到消息,生产者才会收到来自服务器的成功响应。

总结

Kafka 的分区和副本机制是其高性能和高可用的核心设计,合理配置分区数量和副本因子(replication.factor)是优化 Kafka 集群的关键。在实际应用中,需根据业务需求在 吞吐量  数据可靠性 之间找到平衡点。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。