调用balance api或shell命令,实际都是执行HMaster.balance()。
首先判断balanc开关是否打开,balanceSwitch为true则继续执行。然后执行if(this.assignmentManager.isRegionsInTransition()). check是否有region还在事务处理中,如果是则放弃balance,否则执行if(this.serverManager.areDeadServersInProgress()), 如果有crash server还在处理中,也放弃balance
然后调用this.assignmentManager.getAssignmentsByTable(),这是花费代价高的regionserver 和region 信息映射关系集合的clone过程。开始重要的balance过程。
先是一些检核步骤,计算server的负载,以及region的总个数
for (Map.Entry<ServerName, List<HRegionInfo>> server : clusterState.entrySet()) {
List<HRegionInfo> regions = server.getValue();
int sz = regions.size();
if (sz == 0)
emptyRegionServerPresent = true;
numRegions += sz;
serversByLoad.put(new ServerAndLoad(server.getKey(), sz), regions);
}
检查是否需要进行负载均衡
int floor = (int) Math.floor(average * (1 - slop));
int ceiling = (int) Math.ceil(average * (1 + slop));
if (serversByLoad.lastKey().getLoad() <= ceiling
&& serversByLoad.firstKey().getLoad() >= floor) {
// Skipped because no server outside (min,max) range
LOG.info("Skipping load balancing because balanced cluster; " + "servers=" + numServers
+ " " + "regions=" + numRegions + " average=" + average + " " + "mostloaded="
+ serversByLoad.lastKey().getLoad() + " leastloaded="
+ serversByLoad.firstKey().getLoad());
return null;
}