PartitionStateMachine 定义了 Kafka Controller 的分区状态机,用于管理集群中分区的状态信息,每个 Kafka Controller 都定义了自己的分区状态机,但只有在当前 Controller 实例成为 leader 角色时才会启动运行名下的状态机。
它启动逻辑如下:
def startup(): Unit = {
info("Initializing partition state")
// // 初始化本地记录的所有分区状态
initializePartitionState()
info("Triggering online partition state changes")
// 尝试将集群中所有 OfflinePartition 或 NewPartition 状态的可用分区切换成 OnlinePartition 状态
triggerOnlinePartitionStateChange()
debug(s"Started partition state machine with initial state -> ${controllerContext.partitionStates}")
}
private def initializePartitionState(): Unit = {
// 遍历集群中的所有分区
for (topicPartition <- controllerContext.allPartitions) {
// check if leader and isr path exists for partition. If not, then it is in NEW state
// 获取对应分区 leader 副本所在的 brokerId、ISR 集合,以及 controller 年代信息
controllerContext.partitionLeadershipInfo.get(topicPartition) match {
// 存在 leader 副本和 ISR 集合
case Some(currentLeaderIsrAndEpoch) =>
// else, check if the leader for partition is alive. If yes, it is in Online state, else it is in Offline state
// 分区 leader 副本所在的 broker 可用,初始化分区为 OnlinePartition 状态
if (controllerContext.isReplicaOnline(currentLeaderIsrAndEpoch.leaderAndIsr.leader, topicPartition))
// leader is alive
controllerContext.putPartitionState(topicPartition, OnlinePartition)
else
// 分区 leader 副本所在的 broker 不可用,初始化为 OfflinePartition 状态
controllerContext.putPartitionState(topicPartition, OfflinePartition)
case None =>
// 如果不存在,则说明是一个新创建的分区,设置分区状态为 NewPartition
controllerContext.putPartitionState(topicPartition, NewPartition)
}
}
}
Kafka 为分区定义了 4 类状态。
- NewPartition:分区被创建后被设置成这个状态,表明它是一个全新的分区对象。处于这个状态的分区,被 Kafka 认为是“未初始化”,因此,不能选举 Leader。
- OnlinePartition:分区正式提供服务时所处的状态。
- OfflinePartition:分区下线后所处的状态。
- NonExistentPartition:分区被删除,并且从分区状态机移除后所处的状态。

分区 Leader 选举的场景及方法:分区 Leader 选举有 4 类场景。
- OfflinePartitionLeaderElectionStrategy:因为 Leader 副本下线而引发的分区 Leader 选举。
- ReassignPartitionLeaderElectionStrategy:因为执行分区副本重分配操作而引发的分区 Leader 选举。
- PreferredReplicaPartitionLeaderElectionStrategy:因为执行 Preferred 副本 Leader 选举而引发的分区 Leader 选举。
- ControlledShutdownPartitionLeaderElectionStrategy:因为正常关闭 Broker 而引发的分区 Leader 选举。
针对这 4 类场景,分区状态机的 PartitionLeaderElectionAlgorithms 对象定义了 4 个方法,分别负责为每种场景选举 Leader 副本,这 4 种方法是:offlinePartitionLeaderElection;reassignPartitionLeaderElection;preferredReplicaPartitionLeaderElection;controlledShutdownPartitionLeaderElection。
// 分区Leader选举策略接口
sealed trait PartitionLeaderElectionStrategy
// 离线分区Leader选举策略
final case class OfflinePartitionLeaderElectionStrategy(
allowUnclean: Boolean) extends PartitionLeaderElectionStrategy
// 分区副本重分配Leader选举策略
final case object ReassignPartitionLeaderElectionStrategy
extends PartitionLeaderElectionStrategy
// 分区Preferred副本Leader选举策略
final case object PreferredReplicaPartitionLeaderElectionStrategy
extends PartitionLeaderElectionStrategy
// Broker Controlled关闭时Leader选举策略
final case object ControlledShutdownPartitionLeaderElectionStrategy
extends PartitionLeaderElectionStrategy
offlinePartitionLeaderElection 方法的逻辑是这 4 个方法中最复杂的
def offlinePartitionLeaderElection(assignment: Seq[Int], // 这是分区的副本列表
isr: Seq[Int],
liveReplicas: Set[Int], // 该分区下所有处于存活状态的副本
uncleanLeaderElectionEnabled: Boolean, // 脏选举
controllerContext: ControllerContext
): Option[Int] = {
// 从当前分区副本列表中寻找首个处于存活状态的ISR副本
assignment.find(id => liveReplicas.contains(id) && isr.contains(id))
.orElse {
// 如果找不到满足条件的副本,查看是否允许Unclean Leader选举
// 即Broker端参数un

最低0.47元/天 解锁文章
1219

被折叠的 条评论
为什么被折叠?



