HBase源码分析4—Region Balance

30. 1 月 2018 hbase, 数据库 0

易于水平拓展是HBase高性能的重要原因之一。但是随着数据分散到不同节点,容易出现数据倾斜的问题,使得整个集群的效率下降。本章详细讨论下HBase中负载均衡的问题。

入口

HBase源码分析3—HMaster启动过程中提到过,在HMaster启动的最后阶段 finishActiveMasterInitialization 中,HBase会启动一些定时任务,其中就包括负责Region负载均衡的BalanceChore

而balancer对象是在 initializeZKBasedSystemTrackers 中产生的

 

HBase提供了很多种Balancer,曾经默认的叫 SimpleLoadBalancer ,现在默认的是 StochasticLoadBalancer (随机梯度……啊不是,随机负载均衡)。两种balancer的实现都在包 org.apache.hadoop.hbase.master.balancer 中。

Balance过程

BalanceChore 通过调用 HMaster.balance() 来启动balance过程。

首先函数做了一些检查,看集群是否满足做balance的条件,比如正在进行region splitting的时候就不能进行balance,有其他balance进行的时候也不能再进行balance( this.balancer 是用 syncronized 修饰的)。

宏观上看,balance的过程主要分三步:

  • 获取集群信息
  • 获得每个表的balance plan
  • 执行所有plan

plan指的是一个balance的步骤,其中保存了需要移动的region,当前所在的serverName和目的地serverName。

下面展开分析一下三个步骤。

获取集群信息

assignmentManager 是一个与zk集群交互的组件,包含了一些关于node分配方面的函数。 getRegionStates() 方法返回regionStates,这个是 assignmentManager 内使用的管理region状态的一个数据结构,里面的内容跟 hbase:meta 表的内容是一致的。 getAssignmentsByTable() 返回的是以table为聚合维度的region信息,返回的结构为 Map<TableName, Map<ServerName, List<HRegionInfo>>> ,比较直观。

获得balance plan

getClusterStatusWithoutCoprocessor() 用于获取集群信息。为什么要without coprocessor以后再找机会分析下。

接下来就是对每个tabel计算它的balance plan。以默认的方案 StochasticLoadBalancer为例看下这个方案是怎么得到的。

实际调用的方法是 org.apache.hadoop.hbase.master.balancer 包中的 balanceCluster

step 1  balanceMasterRegions()

顾名思义就是对master上的region做平衡操作。分两种:把不该出现在master上的region换出去,把该在master上的region换回来。

这个方法的前半部分实现了“换出去”操作,对maste上的每个region判断一下,如果不必要,就随便找个region server丢了(通过生成RegionPlan实现的,这里并不做真正操作)。如何判断是否要存在master region server上呢?通过方法 shouldBeOnMaster(region)实现。这个方法会去检查regionName是否在一个“免死列表”中( tablesOnMaster ),这个列表中默认包含 hbase:meta,如果想增加其他的region需要在配置中通过配置 hbase.balancer.tablesOnMaster 实现。

方法的后半部分实现的是“换回来”操作,会遍历所有server的所有region进行判断(还用刚才那个函数),如果该回来就生成相应的plan。

如果在这一步中,master region需要做balance,那么cluster的balance plan就不再继续生成了,这一轮就只做master region的balance。

step 2 判断是否有balance的必要

如果除了master region server之外,就剩一个Server了,那就没必要做balance了。在后面几行还有一个 needsBalance(cluster) ,用于计算当前cluster的负载是否需要做balance,具体是对 costFunctions 中的所有估价函数记性计算求和(带权重的),看是否小于某个阈值。估价函数包括:

每个函数都考虑了某方面的问题,比如locality、备份复杂度等等……

step 3 生成balance方案

生成方案的流程很暴力:首先算出一个当前的负载(用needBalance里一样的方法),然后随机生成一个动作,计算操作后是不是比之前更好,如果好就保留,不行就回滚。这种随机的尝试动作有次数上限。最后将cluster的变化组合成plan返回。

执行balance plan

代码来到HMaster.java的1489行左右。之前我们已经获得了一个RegionPlan的ArrayList,下面就是要顺序执行里面的所有plan。主要代码如下:

this.assignmentManager.balance(plan) 这行进行了plan的实际执行操作,具体是(删减了无用代码)