在broker的配置中,auto.leader.rebalance.enable (false)

那么这个leader是如何进行rebalance的?

首先在controller启动的时候会打开一个scheduler,

if (config.autoLeaderRebalanceEnable) { //如果打开outoLeaderRebalance,需要把partiton leader由于dead而发生迁徙的,重新迁徙回去
info("starting the partition rebalance scheduler")
autoRebalanceScheduler.startup()
autoRebalanceScheduler.schedule("partition-rebalance-thread", checkAndTriggerPartitionRebalance,
5, config.leaderImbalanceCheckIntervalSeconds, TimeUnit.SECONDS)
}

定期去做,

checkAndTriggerPartitionRebalance

这个函数逻辑,就是找出所有发生过迁移的replica,即

topicsNotInPreferredReplica

并且判断如果满足imbalance比率,即自动触发leader rebalance,将leader迁回perfer replica

关键要理解什么是preferred replicas?

preferredReplicasForTopicsByBrokers =
controllerContext.partitionReplicaAssignment.filterNot(p => deleteTopicManager.isTopicQueuedUpForDeletion(p._1.topic)).groupBy {
case(topicAndPartition, assignedReplicas) => assignedReplicas.head
}
 partitionReplicaAssignment: mutable.Map[TopicAndPartition, Seq[Int]] 
TopicAndPartition可以通过topic name和partition id来唯一标识一个partition,Seq[int],表示brokerids,表明这个partition的replicas在哪些brokers上面

从partition的ReplicaAssignment里面过滤掉delete的topic,然后按照assignedReplicas.head进行groupby,就是按照Seq中的第一个brokerid

意思就是说,默认每个partition的preferred replica就是第一个被assign的replica

groupby的结果就是,每个broker,和应该以该broker作为leader的所有partition,即

case(leaderBroker, topicAndPartitionsForBroker)

那么找出里面当前leader不是preferred的,即发生过迁移的,

很简单,直接和leaderAndIsr里面的leader进行比较,如果不相等就说明发生过迁徙

topicsNotInPreferredReplica =
topicAndPartitionsForBroker.filter {
case(topicPartition, replicas) => {
controllerContext.partitionLeadershipInfo.contains(topicPartition) &&
controllerContext.partitionLeadershipInfo(topicPartition).leaderAndIsr.leader != leaderBroker
}
}

并且只有当某个broker上的imbalanceRatio大于10%的时候,才会触发rebalance

imbalanceRatio = totalTopicPartitionsNotLedByBroker.toDouble / totalTopicPartitionsForBroker

对每个partition的迁移过程,

首先preferred的broker要是活着的,并且当前是没有partition正在进行reassign或replica election的,说明这个过程是不能并行的,同时做reassign很容易冲突

// do this check only if the broker is live and there are no partitions being reassigned currently
// and preferred replica election is not in progress
if (controllerContext.liveBrokerIds.contains(leaderBroker) &&
controllerContext.partitionsBeingReassigned.size == 0 &&
controllerContext.partitionsUndergoingPreferredReplicaElection.size == 0 &&
!deleteTopicManager.isTopicQueuedUpForDeletion(topicPartition.topic) &&
controllerContext.allTopics.contains(topicPartition.topic)) {
onPreferredReplicaElection(Set(topicPartition), true)

onPreferredReplicaElection

还是通过partitionStateMachine,来改变partition的状态

partitionStateMachine.handleStateChanges(partitions, OnlinePartition, preferredReplicaPartitionLeaderSelector)

partitionStateMachine会另外分析,这里只需要知道,当前partition的状态是,OnlinePartition –> OnlinePartition

并且是以preferredReplicaPartitionLeaderSelector,作为leaderSelector的策略

 

PreferredReplicaPartitionLeaderSelector

策略很简单,就是把leader换成preferred replica

def selectLeader(topicAndPartition: TopicAndPartition, currentLeaderAndIsr: LeaderAndIsr): (LeaderAndIsr, Seq[Int]) = {
val assignedReplicas = controllerContext.partitionReplicaAssignment(topicAndPartition)
val preferredReplica = assignedReplicas.head //取AR第一个replica作为preferred
// check if preferred replica is the current leader
val currentLeader = controllerContext.partitionLeadershipInfo(topicAndPartition).leaderAndIsr.leader
if (currentLeader == preferredReplica) { //如果当前leader就是preferred就不需要做了
throw new LeaderElectionNotNeededException("Preferred replica %d is already the current leader for partition %s" .format(preferredReplica, topicAndPartition))
} else {
info("Current leader %d for partition %s is not the preferred replica.".format(currentLeader, topicAndPartition) + " Trigerring preferred replica leader election")
// check if preferred replica is not the current leader and is alive and in the isr
if (controllerContext.liveBrokerIds.contains(preferredReplica) && currentLeaderAndIsr.isr.contains(preferredReplica)) { //判断当前preferred replica所在broker是否活,是否在isr中
(new LeaderAndIsr(preferredReplica, currentLeaderAndIsr.leaderEpoch + 1, currentLeaderAndIsr.isr, currentLeaderAndIsr.zkVersion + 1), assignedReplicas) //产生新的leaderAndIsr
} else {
throw new StateChangeFailedException("Preferred replica %d for partition ".format(preferredReplica) +
"%s is either not alive or not in the isr. Current leader and ISR: [%s]".format(topicAndPartition, currentLeaderAndIsr))
}
}
}
}

Apache Kafka源码分析 - autoLeaderRebalanceEnable的更多相关文章

  1. Apache Kafka源码分析 – Broker Server

    1. Kafka.scala 在Kafka的main入口中startup KafkaServerStartable, 而KafkaServerStartable这是对KafkaServer的封装 1: ...

  2. apache kafka源码分析-Producer分析---转载

    原文地址:http://www.aboutyun.com/thread-9938-1-1.html 问题导读1.Kafka提供了Producer类作为java producer的api,此类有几种发送 ...

  3. Apache Kafka源码分析 - kafka controller

    前面已经分析过kafka server的启动过程,以及server所能处理的所有的request,即KafkaApis 剩下的,其实关键就是controller,以及partition和replica ...

  4. Apache Kafka源码分析 – Controller

    https://cwiki.apache.org/confluence/display/KAFKA/Kafka+Controller+Internalshttps://cwiki.apache.org ...

  5. Apache Kafka源码分析 – Log Management

    LogManager LogManager会管理broker上所有的logs(在一个log目录下),一个topic的一个partition对应于一个log(一个log子目录)首先loadLogs会加载 ...

  6. Apache Kafka源码分析 - KafkaApis

    kafka apis反映出kafka broker server可以提供哪些服务,broker server主要和producer,consumer,controller有交互,搞清这些api就清楚了 ...

  7. Apache Kafka源码分析 – Replica and Partition

    Replica 对于local replica, 需要记录highWatermarkValue,表示当前已经committed的数据对于remote replica,需要记录logEndOffsetV ...

  8. Apache Kafka源码分析 - ReplicaStateMachine

    startup 在onControllerFailover中被调用, /** * Invoked on successful controller election. First registers ...

  9. Apache Kafka源码分析 - PartitionStateMachine

    startup 在onControllerFailover中被调用, initializePartitionState private def initializePartitionState() { ...

随机推荐

  1. laravel框架session使用教程

    laravel是一款php框架了,在使用laravel时会碰到session使用问题了,在使用过程中碰到一些问题与一些应用的例子. 用Laravel开发应用,把原有的代码copy过来,以前的代码ses ...

  2. 解决Inno Setup制作安装包无法创建桌面快捷方式的问题

    转自:http://yedward.net/?id=104 昨天想把个java程序做成exe安装软件,然后就去下载了Inno Setup这个软件安装包制作软件,Inno Setup这个软件确实非常好用 ...

  3. C++ Primer与c++编程思想的比较(转)

    C++primer是最经典的c++教材之一,它的经典程度要超过thinking in c++.连thinking in c++作者本人都说他写这本书在某种程度上是让读者更好的理解C++primer.但 ...

  4. ListView系列(七)——Adapter内的onItemClick监听器四个arg参数 (转)

    举个例子你会理解的更快:X, Y两个listview,X里有1,2,3,4这4个item,Y里有a,b,c,d这4个item.如果你点了b这个item.如下: public void onItemCl ...

  5. SU Demos-02Filtering-05Suk1k2filter

    本人数学不咋地,本demo也是一知半解,敬请谅解. 这是生成的脉冲数据

  6. Xamarin.Android编译提示找不到mscorlib.dll.so文件

    Xamarin.Android编译提示找不到mscorlib.dll.so文件 错误信息:AOT module ‘mscorlib.dll.so’ not found: Cannot load lib ...

  7. 水题 Codeforces Round #300 A Cutting Banner

    题目传送门 /* 水题:一开始看错题意,以为是任意切割,DFS来做:结果只是在中间切出一段来 判断是否余下的是 "CODEFORCES" :) */ #include <cs ...

  8. 贪心 POJ 2109 Power of Cryptography

    题目地址:http://poj.org/problem?id=2109 /* 题意:k ^ n = p,求k 1. double + pow:因为double装得下p,k = pow (p, 1 / ...

  9. 【转】执行脚本出现bin/bash: bad interpreter: No such file or directory

    [转自]http://blog.csdn.net/wind19/article/details/4822666 错误原因之一很有可能是你的脚本文件是DOS格式的, 即每一行的行尾以/r/n来标识, 其 ...

  10. Grunt配置文件编写技巧及示范

    受益于grunt这么久,继续分享关于grunt的一些技巧.grunt确实是前端项目中不可或缺的提升效率的工具.第一次接触grunt是在去年7月份,开始有接触LESS.Coffee Script的等需要 ...