PrefferedReplicaElectionListener负责监听/admin/preferred_replica_election,当需要进行优先副本选举的时候回指定分区的信息写入这个这个节点,然后触发PrefeeredReplicaElectionListener进行处理。
class PreferredReplicaElectionListener(controller: KafkaController) extends IZkDataListener with Logging {
this.logIdent = "[PreferredReplicaElectionListener on " + controller.config.brokerId + "]: "
val zkUtils = controller.controllerContext.zkUtils
val controllerContext = controller.controllerContext
/**
* Invoked when some partitions are reassigned by the admin command
* @throws Exception On any error.
*/
@throws(classOf[Exception])
def handleDataChange(dataPath: String, data: Object) {
debug("Preferred replica election listener fired for path %s. Record partitions to undergo preferred replica election %s"
.format(dataPath, data.toString))
inLock(controllerContext.controllerLock) {
// 获取需要进行优选副本选举TopicAndPartition列表
val partitionsForPreferredReplicaElection = PreferredReplicaLeaderElectionCommand.parsePreferredReplicaElectionData(data.toString)
if(controllerContext.partitionsUndergoingPreferredReplicaElection.size > 0)
info("These partitions are already undergoing preferred replica election: %s"
.format(controllerContext.partitionsUndergoingPreferredReplicaElection.mkString(",")))
// 过滤掉正在进行优选副本选举的分区
val partitions = partitionsForPreferredReplicaElection -- controllerContext.partitionsUndergoingPreferredReplicaElection
// 过滤掉待删除的topic分区
val partitionsForTopicsToBeDeleted = partitions.filter(p => controller.deleteTopicManager.isTopicQueuedUpForDeletion(p.topic))
if(partitionsForTopicsToBeDeleted.size > 0) {
error("Skipping preferred replica election for partitions %s since the respective topics are being deleted"
.format(partitionsForTopicsToBeDeleted))
}
// 对剩余的分区调用onPreferredReplicaElection进行选举
controller.onPreferredReplicaElection(partitions -- partitionsForTopicsToBeDeleted)
}
}
}
def onPreferredReplicaElection(partitions: Set[TopicAndPartition], isTriggeredByAutoRebalance: Boolean = false) {
info("Starting preferred replica leader election for partitions %s".format(partitions.mkString(",")))
try {
// 把参与优先副本选举的分区添加到partitionsUndergoingPreferredReplicaElection集合中
controllerContext.partitionsUndergoingPreferredReplicaElection ++= partitions
// 把对应的topic标记为不可删除
deleteTopicManager.markTopicIneligibleForDeletion(partitions.map(_.topic))
// 将partition装换为onlinePartition状态,除了重新选leader,还会更小点zk中的数据
partitionStateMachine.handleStateChanges(partitions, OnlinePartition, preferredReplicaPartitionLeaderSelector)
} catch {
case e: Throwable => error("Error completing preferred replica leader election for partitions %s".format(partitions.mkString(",")), e)
} finally {
// 清理partitionsUndergoingPreferredReplicaElection和zk上的相关数据
removePartitionsFromPreferredReplicaElection(partitions, isTriggeredByAutoRebalance)
// 把topic标记为可删除
deleteTopicManager.resumeDeletionForTopics(partitions.map(_.topic))
}
}