第四章:主题和分区
4.1 主题管理
一般通过kafka-topics.sh脚本来执行包括创建主题、查看主题信息、修改主题和删除主题等操作
4.1.1 创建主题
-
如果broker端配置参数auto.create.topics.enable设置为 true(默认值就是 true),那么当生产者向一个尚未创建的主题发送消息时,会自动创建一个分区数为num.partitions(默认值为1)、副本因子为default.replication.factor(默认值为1)的主题。一般情况下不推荐设置成true
-
建议通过kafka-topics.sh 脚本来创建主题
-
主题、分区、副本和 Log (日志)的关系
4.2 KafkaAdminClient
从0.11.0.0版本开始,Kafka提供了工具类org.apache.kafka.clients.admin.KafkaAdminClient来实现部分Kafka的管理功能,主要有以下几个方法
- 创建主题:CreateTopicsResult createTopics(Collection<NewTopic> newTopics)
- 删除主题:DeleteTopicsResult deleteTopics(Collection<String> topics)
- 列出所有可用的主题:ListTopicsResult listTopics()
- 查看主题的信息:DescribeTopicsResult describeTopics(Collection<String> topicNames)
- 查询配置信息:DescribeConfigsResult describeConfigs(Collection<ConfigResource> resources)
- 修改配置信息:AlterConfigsResult alterConfigs(Map<ConfigResource, Config> configs)
- 增加分区:CreatePartitionsResultcreatePartitions(Map<String, NewPartitions> newPartitions)
4.3 分区管理
本节主要介绍与分区相关的知识和操作,包括优先副本的选举、分区重分配、复制限流、修改副本因子等内容
4.3.1 优先副本的选举
一般而言,对于同一个分区,同一个broker节点中不可能出现它的多个副本,即 Kafka集群的一个 broker中最多只能有它的一个副本
- 背景:leader宕机引起的集群负载均衡失衡,从而影响整体的健壮性和稳定性
- 在创建主题时,该主题的分区及副本会尽可能均匀地分布到Kafka集群的各个broker节点上,对应的leader副本的分配也比较均匀(下图中,三个分区的leader节点分别在broker 0、1、2上)
- 在创建主题时,该主题的分区及副本会尽可能均匀地分布到Kafka集群的各个broker节点上,对应的leader副本的分配也比较均匀(下图中,三个分区的leader节点分别在broker 0、1、2上)
- 随着时间的更替,Kafka集群的broker节点不可避免地会遇到宕机或崩溃的问题,当分区的leader节点发生故障时,其中一个follower节点就会成为新的 leader节点,这样就会导致集群的负载不均衡,从而影响整体的健壮性和稳定性(下图中,原本分区1的leader节点2宕机,现在变成了0,使得整体负载失衡,节点0承载了2个leader节点)
- 如何应对:为了能够有效地治理负载失衡的情况,Kafka引入了优先副本(preferred replica)的概念
- 优先副本:指在AR集合列表中的第一个副本。如下图主题topic-partitions中,分区0的AR集合列表为[1,2,0],那么分区0的优先副本即为1
- 理想情况下,优先副本就是该分区的leader副本。Kafka要确保所有主题的优先副本在Kafka集群中均匀分布,这样就保证了所有分区的leader均衡分布
- 优先副本:指在AR集合列表中的第一个副本。如下图主题topic-partitions中,分区0的AR集合列表为[1,2,0],那么分区0的优先副本即为1
- 优先副本的选举:指通过一定的方式促使优先副本选举为leader副本,以此来促进集群的负载均衡,这一行为也可以称为"分区平衡"
- 在Kafka中可以提供分区自动平衡的功能:通过设置broker端参数auto.leader.rebalance.enable=true(默认也为true)
- 设置该参数开启后,Kafka会启动一个定时任务,定时轮询所有的broker节点,计算每个broker节点的分区不平衡率,如果超过leader.imbalance.per.broker.percentage参数(默认10%),则会自动执行优先副本的选举动作以求分区平衡
- broker中的分区不平衡率 = 非优先副本的leader个数 / 分区总数
- 不过生产环境中不建议将该参数设置为true,因为可能会引起负面性能问题(比如电商大促波峰期阻塞了业务)
4.3.2 分区重分配(Partition Reassignment)
- 背景:当集群中某一节点(broker)下线或新增,会打破原先集群的负载均衡。为解决该问题,引入重分配的工作,它可以在集群扩容、 broker节点失效的场景下对分区进行迁移
- 重分配原理:先通过控制器为每个分区添加新副本(增加副本因子),新的副本将从分区的leader副本那里复制所有的数据。根据分区的大小不同, 复制过程可能需要花一些时间。在复制完成之后,控制器将旧副本从副本清单里移除(恢复为原先的副本因子数)
- 弊端:分区重分配对集群的性能有很大的影响,需要占用额外的资源,比如网络和磁盘。在实际操作中,我们将降低重分配的粒度,分成多个小批次来执行,以此来将负面的影响降到最低
- 与rebalance(再平衡)的区别
- 重分配:作用在broker层面,是broker与partition间的分配;通常是为了管理优化集群手动触发
- 触发条件:broker加入/离开集群
- 目的:维护集群负载均衡(指broker和partition间)
- 再平衡:作用在消费组层面(新增/下线消费者),Rebalance的目的是确保分区在consumer group成员之间平均分配,以便每个consumer都有分区去消费;通常是Kafka协调器自动触发的
- 触发条件:消费者组中的成员发生变化(如新消费者加入、现有消费者离开或失败)
- 目的:维护partition与消费者之间的平衡
- 重分配:作用在broker层面,是broker与partition间的分配;通常是为了管理优化集群手动触发
4.3.3 复制限流
- 在4.3.2中提到重分配本质在于数据复制。即先增加新的副本,然后进行数据同步,最后删除旧的副本来达到最终的目的
- 数据复制会占用额外的资源,这时就需要有一个限流的限制
- broker级别限流参数
- follower.replication.throttled.rate:follower副本复制的速度
- leader.replicatioη.throttled.rate:leader副本传输的速度
- topic级别限流参数
- leader.replication.throttled.replicas
- follower.replication.throttled.replicas
4.3.4 修改副本因子
- 指创建主题之后修改副本因子(副本数),通过kafka-reassign-partition.sh脚本实现
4.4 分区和性能的考量因素
- Kafka本身提供的性能测试工具
- kafka-producer-perf-test.sh:用于生产者性能测试
- kafka-consumer-perf-test.sh:用于消费者性能测试
- 分区与吞吐量的关系
- 如何衡量消息中间件性能:吞吐量(广义来说还包含消息延迟)
- 影响吞吐量的因素:消息大小、消息压缩方式、消息发送方式(同步/异步)、消息确认类型(acks)、副本因子等参数
- 分区与吞吐量的测试结论:从吞吐量方面考虑,增加合适的分区数可以在一定程度上提升整体吞吐量,但超过对应的阐值之后吞吐量不升反降(分区太多会引起kafka进程崩溃)
- 分区太多的缺点
- 分区数越多会让Kafka的正常启动和关闭的耗时变得越长,增加日志清理的耗时
- 分区数会占用文件描述符,分区太多会增加文件句柄开销
- 分区太多的缺点
- 如何考量合适的分区数
- 是否要保证顺序消费:分区数只能为1
- 一般情况下,考虑未来2年的吞吐量,及key与分区数是否存在相关定制化规则