分区是主题的子集,每个主题可以被分割成多个分区,一个分区有一个主副本(Leader)及一个或多个从(Follower)副本。分区允许将数据分布在多个broker上,这样可以提高数据的处理能力、并行性及可靠性。
每个分区在物理上是一个有序、不可变的消息序列,存储为一系列连续的、有序的日志文件。
1 分区管理
1.1 优选副本的选举
只有leader副本对外提供读写服务,而follower副本只负责在内部进行消息同步。忽略不同分区负载情况不同这一因素,broker上leader副本个数的多少决定了这个节点的负载高低。
创建主题时,该主题的分区及副本会尽可能均匀分布在集群的各个broker节点,leader副本也会均匀分布。随着时间推移,假如某个leader副本所在的broker宕机了,那么就会在集群的其他broker中重新选举leader,当该宕机的broker重新上线加入集群时,其只能成为一个follower。这样一来,leader的副本就变得不均衡。
1.1.1 优先副本
图 主题par3 的分区副本分配详情
分区的AR(Assigned Replicas)集合是在新区被创建时,Kafka根据配置来确定该分区的所有副本,并将这些副本组成AR集合。
上图中,分区0的AR集合为 [1,0,2],分区2的AR集合为[0,2,1]。
优选副本是指AR集合中的第一个副本。例如分区0的优选副本为1。AR集合在broker发生故障或重新上线时是不会改变的。
理想情况下,优选副本就是该分区的leader副本,而优选副本选举是指通过一定的方式促使优选副本选举为leader副本。
1.1.2 优选副本自动平衡
将broker端的参数auto.leader.rebalance.enable设置为true(默认值)。Kafka会启动一个定时任务,来自动执行优选副本选举动作。
生产环境建议关闭这个,因为其自动执行优选副本选举动作的时间无法自主掌控,如果在业务高峰期执行,那么会造成业务阻塞、超时等。
1.1.3 手动执行优选副本选举
bin/kafka-preferred-replica-election.sh --zookeeper localhost:2181
该脚本还提供了path-to-json-file 参数来小批量地对部分分区执行优选副本的选择操作。以下为该文件的示范内容。
{
"partitions": [
{
"partition": 0,
"topic": "par3"
},
{
"partition": 1,
"topic": "par3"
}
]
}
bin/kafka-preferred-replica-election.sh --zookeeper localhost:2181 --path-to-json-file par3.json
1.2 分区重分配
1)如果某分区是单副本,且所在节点突然宕机下线,那么这个分区就变得不可用,在节点恢复前,相应的数据就处于丢失状态。
2)某个节点有多个分区副本,如果该节点宕机,Kafka并不会将这些失效的分区副本自动迁移到集群中剩余的可用broker节点上。
3)当集群新增broker节点时,只有新建的主题分区才有可能被分配到这个节点上,之前的主题分区不会自动分配新增的节点。
4)当要对集群的一个节点进行有计划的下线时,为了保证分区及副本的合理分配,我们希望通过某种方式将该节点的分区副本迁移到其他的可用节点上。
为了解决这些问题,需要进行分区重分配。
1.2.1 分区副本重分配步骤
需求,主题par2 副本所在的一个broker(id为1)要下架,需要将其上的分区副本迁移出去。
图 主题par3 的分区副本分配详情
1)创建一个包含主题清单的JSON文件。
文件内容为要进行分区重分配的主题清单,文件名假定为par2-reassign.json,内容如下:
{
"topics": [
{
"topic": "par2"
}
]
}
2)根据上面的JSON文件和指定要分配的broker节点列表。生成一份重分配方案。
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --generate --topics-to-move-json-file par2-reassign.json --broker-list 0,2
图 生成的重分配方案
其中,Current partition replica assignment 为当前的分区副本分配方案。而Proposed partition reassignment configuration 为生成的新分配方案。
3)复制上面新分配方案,保存为new-par2.json,然后执行重分配脚本。
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --execute --reassignment-json-file new-par2.json
图 执行重分配脚本
最后查看par2的分区副本分配详情
图 重分配后par2 的分区副本分配详情
1.2.2 修改副本因子
创建主题后,可以修改分区的个数,同样也可修改副本因子(副本数)。
上面分区副本重分配的第三步,修改new-par2.json文件来修改副本因子,然后执行重分配脚本。命名为par2-2.json。
{
"version": 1,
"partitions": [
{
"topic": "par2",
"partition": 1,
"replicas": [2],
"log_dirs": ["any"]
},
{
"topic": "par2",
"partition": 0,
"replicas": [0, 2],
"log_dirs": ["any", "any"]
}]
}
图 修改副本因子后的par2 副本分配详情
2 分区数与吞吐性能
对生产者而言,每个分区的数据写入是完全可以并行化的;对消费者而言,Kafka只允许单个分区中的消息被一个消费者线程消费,一个消费组的消费并行度完全依赖于所消费的分区数。
如此看来,一个主题的分区数越多,吞吐性能越好。但实际并非如此。一旦分区数超过某个阈值,吞吐性能不升反降。
2.1 性能测试工具
Kafka 本身提供了用于生产者性能测试的kafka-producer-perf.test.sh和用于消费者性能测试的kafka-consumer-perf-test.sh。
2.1.1 生产者性能测试
bin/kafka-producer-perf-test.sh --topic par3 --num-records 100000 --record-size 1024 --throughput -1 --producer-props bootstrap.servers=localhost:9092 acks=1
向主题par3 发送10万条大小为1024B的消息,生产者对应的acks为1(分区中至少有1个副本收到这条消息,才算成功写入).
图 向生产者发送测试消息
2.1.2 消费者性能测试
bin/kafka-consumer-perf-test.sh --topic par3 --messages 100000 --broker-list localhost:9092
消费主题par3 的10万条消息。