优先副本的选举
Kafka 通过副本机制来提升服务的可靠性,但是只有 leader 副本提供对外的读写服务,这样就意味着,当 leader 丢失时,需要从 follower 副本中选举一个 leader 来提供服务。Kafka 在我们创建 Topic 的时候,会尽量的把分区和副本均匀的分布在所有的 broker 上,同时 leader 副本也会比较均匀,以此来保证整个集群的负载均衡和稳定性。例如我们创建一个 Topic:
1 | [root@tnode2 bin]# ./kafka-topics.sh --create --zookeeper tnode3:2181 --replication-factor 3 --partitions 3 --topic topic003 |
可以看出,三个分区分别在不同的 broker 上,同时每个分区的每个副本都在不同的 broker 上 ( 副本数是不能超过 broker 数的,否则创建时会报错 ) ,另外,三个分区的 leader 也分布在不同的 broker 上。但是时间久了,总会有 leader 副本丢失,导致 副本的选举,重新出现新的 leader。假设我们将 broker2 重启一下,再看 Topic 情况。
1 | [root@tnode2 bin]# ./kafka-topics.sh --describe --zookeeper tnode3:2181 --topic topic003 |
很明显,在重启之后,Topic 的 leader副本发生了变化,即发生了副本的重新选举,如果这种选举经常发生的话,就很有可能导致负载很不均衡。在 Kafka 中,为了保证集群的稳定性和可靠性,引入了一个优先副本的机制,即在创建 Topic 的时候,AR 列表的第一个副本为 优先副本,尽可能会将它选为 leader 副本。
同时,为了保证所有分区的 leader 副本均衡分布,Kafka 有几种方式来进行分区平衡。
broker端参数
auto.leader.rebalance.enable 默认为 true,即开启自动分区平衡。当开启自动时,Kafka 的控制器会启动定时任务,定时(周期由
leader.imbalance.check.interval.seconds
控制,默认为300秒,即 5分钟)轮询所有 broker 节点,计算每个 broker 节点的分区不平衡率(非优先副本 leader 数 / 分区总数),如果超过一定值(leader.imbalance.per.broker.percentage
,默认为10%)。不建议在生产环境中开启自动分区平衡,因为自动平衡的时间无法控制,可能会造成不必要的麻烦。尽量对不平衡率进行监控,然后手动进行分区平衡
分区平衡脚本
kafka-preferred-replica-election.sh
1
2
3
4
5
6
7
8[root@tnode2 bin]# ./kafka-preferred-replica-election.sh --zookeeper tnode3:2181
Created preferred replica election path with {"version":1,"partitions":[{"topic":"LxmTest","partition":2},{"topic":"FLINK-TOPIC-1","partition":0},{"topic":"__consumer_offsets","partition":34},{"topic":"LxmTest","partition":5},{"topic":"SINK-TEST-TOPIC","partition":0},{"topic":"__consumer_offsets","partition":36},{"to....
[root@tnode2 bin]# ./kafka-topics.sh --describe --zookeeper tnode3:2181 --topic topic003
Topic:topic003 PartitionCount:3 ReplicationFactor:3 Configs:
Topic: topic003 Partition: 0 Leader: 0 Replicas: 0,2,1 Isr: 0,1,2
Topic: topic003 Partition: 1 Leader: 1 Replicas: 1,0,2 Isr: 1,0,2
Topic: topic003 Partition: 2 Leader: 2 Replicas: 2,1,0 Isr: 1,0,2在使用 此脚本时,会将集群中所有的 Topic 的分区进行分区平衡的操作,如果集群规模较大,直接这样使用可能也会影响集群的可用性。所幸此脚本还有参数
--path-to-json-file
来批量进行分区平衡,用法如下:1
2
3
4
5
6
7
8
9
10
11
12
13[root@tnode2 bin]# ./kafka-topics.sh --describe --zookeeper tnode3:2181 --topic topic003
Topic:topic003 PartitionCount:3 ReplicationFactor:3 Configs:
Topic: topic003 Partition: 0 Leader: 0 Replicas: 0,2,1 Isr: 0,1
Topic: topic003 Partition: 1 Leader: 1 Replicas: 1,0,2 Isr: 1,0
Topic: topic003 Partition: 2 Leader: 1 Replicas: 2,1,0 Isr: 1,0
[root@tnode2 bin]# ./kafka-preferred-replica-election.sh --zookeeper tnode3:2181 --path-to-json-file election.json
Created preferred replica election path with {"version":1,"partitions":[{"topic":"topic003","partition":0},{"topic":"topic003","partition":1},{"topic":"topic003","partition":2}]}
Successfully started preferred replica election for partitions Set([topic003,0], [topic003,1], [topic003,2])
[root@tnode2 bin]# ./kafka-topics.sh --describe --zookeeper tnode3:2181 --topic topic003
Topic:topic003 PartitionCount:3 ReplicationFactor:3 Configs:
Topic: topic003 Partition: 0 Leader: 0 Replicas: 0,2,1 Isr: 0,1,2
Topic: topic003 Partition: 1 Leader: 1 Replicas: 1,0,2 Isr: 1,0,2
Topic: topic003 Partition: 2 Leader: 2 Replicas: 2,1,0 Isr: 1,0,2
在生产中,尽量使用批量分区平衡的方式来进行平衡分区 leader,同时也要避开业务高峰期。
分区重分配
在 Kafka 中,如果发生 broker 节点宕机、broker 下线、新增 broker 等情况时,会发生部分副本不可用或者新 broker 无副本,这样会导致集群的负载不均衡。为了解决这类问题,就出现了分区重分配的策略,见文档
复制限流
副本间的复制限流有两种方式:
kafka-config.sh 脚本来实现
broker 端有两个参数与复制限流相关:
follower.replication.throttled.rate
和leader.replication.throttled.rate
,一个用于设置 follower 的复制速度,一个用于设置 leader 的传输速度,单位均为 B/s。示例:先设置两个参数值,后再删除两个设置。1
2
3
4
5
6
7
8[root@tnode2 bin]# ./kafka-configs.sh --zookeeper tnode3:2181 --entity-type brokers --entity-name 2 --alter --add-config follower.replication.throttled.rate=1024,leader.replication.throttled.rate=1024
Completed Updating config for entity: brokers '2'.
[root@tnode2 bin]# ./kafka-configs.sh --zookeeper tnode3:2181 --entity-type brokers --entity-name 2 --describe
Configs for brokers '2' are leader.replication.throttled.rate=1024,follower.replication.throttled.rate=1024
[root@tnode2 bin]# ./kafka-configs.sh --zookeeper tnode3:2181 --entity-type brokers --entity-name 2 --alter --delete-config follower.replication.throttled.rate,leader.replication.throttled.rate
Completed Updating config for entity: brokers '2'.
[root@tnode2 bin]# ./kafka-configs.sh --zookeeper tnode3:2181 --entity-type brokers --entity-name 2 --describe
Configs for brokers '2' areTopic 端也有两个参数与复制限流相关:follower.replication.throttled.replicas 和 leader.replication.throttled.replicas ,用法和上面的类似,
--entity-type
为 topic ,--entity-name
为 topicName。kafka-reassign-partition.sh 脚本实现
修改副本数
增加副本数:和分区重分配的用法一样,只不过需要执行的分区文件不一样,如下:(原来分区只有2个副本,这里添加第三个副本)。
1 | {"version":1,"partitions":[ |
减少副本数:和增加类似,减少 replicas 列表中副本数和对应的 log_dirs 列表 即可
选择合适的分区数
同等外部条件下,随着分区数的增加,吞吐量会随着增加,直到一个临界值后,分区数再增加,吞吐量下降…
因此,对于新 Kafka 集群,最好先使用性能测试工具,测出合适的分区数范围。如果不测的话,普遍使用broker 的整数倍 来作为分区数。
分区数也有上限,上限在于系统的打开文件上限数。