bigywater.tech
Kafka 内部原理 · 46

Partition Leader 是怎么选出来的

真实创建一个6分区3副本的topic,观察初始leader的分布规律,再kill掉一个broker,看只有哪些分区会真实换leader、新leader又是怎么被选出来的。

2/6
kill一个broker后真实受影响的分区数
按顺序跳过
新leader真实的选取规则:排除死副本后取剩下最靠前的

验证:一个topic刚创建时,leader真实是怎么分布的

命令 · shell $ kafka-topics.sh --bootstrap-server localhost:19092 --create --topic leader-demo --partitions 6 --replication-factor 3 $ kafka-topics.sh --bootstrap-server localhost:19092 --describe --topic leader-demo
真实实测 · 本机执行输出
Partition 0  Leader: 1  Replicas: 1,2,3  Isr: 1,2,3
Partition 1  Leader: 2  Replicas: 2,3,1  Isr: 2,3,1
Partition 2  Leader: 3  Replicas: 3,1,2  Isr: 3,1,2
Partition 3  Leader: 1  Replicas: 1,3,2  Isr: 1,3,2
Partition 4  Leader: 3  Replicas: 3,2,1  Isr: 3,2,1
Partition 5  Leader: 2  Replicas: 2,1,3  Isr: 2,1,3

真实规律非常直白:每个分区的leader,就是它Replicas列表里的第一个broker(Kafka内部把这个叫preferred leader)。6个分区的replicas列表,真实是Controller创建topic时用round-robin算法从1,2,3三个broker里错开排列出来的,结果就是初始leader真实也均匀落在了1、2、3三个broker上各2个,没有谁真实吃满全部负载。

验证:kill掉broker1,只有它领导的分区真实换了leader

命令 · shell $ kill -9 <broker1的pid> $ sleep 5 $ kafka-topics.sh --bootstrap-server localhost:19094 --describe --topic leader-demo
真实实测 · 本机执行输出
Partition 0  Leader: 2 (原来是1)  Replicas: 1,2,3  Isr: 2,3
Partition 1  Leader: 2 (没变)     Replicas: 2,3,1  Isr: 2,3
Partition 2  Leader: 3 (没变)     Replicas: 3,1,2  Isr: 3,2
Partition 3  Leader: 3 (原来是1)  Replicas: 1,3,2  Isr: 3,2
Partition 4  Leader: 3 (没变)     Replicas: 3,2,1  Isr: 3,2
Partition 5  Leader: 2 (没变)     Replicas: 2,1,3  Isr: 2,3

真实只有分区0和分区3变了——这两个恰好是原本由broker1领导的分区,其余4个分区的leader真实原封不动。新leader也不是随便选的:分区0的Replicas是[1,2,3],broker1死后剩下[2,3],真实选中的新leader是2(排在3前面);分区3的Replicas是[1,3,2],剩下[3,2],真实选中的是3。两次真实都是"排除掉死掉的副本之后,剩下列表里最靠前的那个"。

结论

Partition Leader的选举真实分两个阶段:topic刚创建时,Controller用round-robin把每个分区的副本顺序错开排列,排在最前面的(preferred leader)就是初始leader,这一步真实的目的是让leader负载在broker之间尽量均匀。运行时如果当前leader真实挂了,Controller(参见《Kafka Controller 到底负责什么》)会检测到故障,从这个分区剩下的ISR成员里,按replicas原本的顺序真实挑一个还活着的顶上——不是随机选,也不是选负载最轻的那个,就是简单地"跳过死掉的,找下一个"。这个规则足够简单,付出的代价是长期运行后leader可能会真实逐渐向少数broker倾斜,这也是为什么Kafka另外还提供了kafka-leader-election.sh --election-type preferred这样的手动命令,可以在broker恢复后主动把leader真实迁回原本的preferred leader,重新拉平负载。

分步演示:6个分区,只有2个真实受到影响

每一步都是本文上面用kafka-topics.sh --describe跑出来的原始结果。

只有真正受影响的分区才会真实换leader
这一步新验证的分区状态

    参考与说明

    • 数据来自本机3节点Kafka 4.3.1集群,topic leader-demo(6分区3副本),真实kill -9掉broker1并对比前后的describe输出。
    • 和《KRaft Controller Quorum 如何选主》一起看:那篇的选主对象是controller quorum自己的leader,这篇的选主对象是数据分区的leader,两者都由同一个Controller角色触发,但选举机制完全不同——分区leader选举没有Raft投票,只是简单地在ISR里按顺序挑一个。
    • 没有验证:unclean.leader.election.enable=true时(允许ISR之外的副本上位)真实的选举差异,本系列前面的《Unclean Leader Election》一文已经单独覆盖。
    京ICP备2026067502号-1京公网安备11010502063487号