HDFS Balancer原理及优化方向
一、前言
集群在长时间使用过程中,难免会出现节点间数据不均衡的情况。尤其是在集群新增节点,或者人为的调整了副本数量以后,数据多的节点可以达到95%以上,少的节点连10%都不到。hadoop中提供了Balance工具来在节点间移动数据以达到集群节点数据平衡的效果。集群数据不平衡现象越严重,越有必要调整和优化Balancer的速度。
二、HDFS Balancer流程及原理
2.1 Balancer 使用
HDFS Balancer使用时可以调整的参数如下:
-policy <policy> | datanode(默认值):如果每个datanode均衡,则群集是平衡的。 blockpool:如果每个datanode中的每个块池都是平衡的,则群集是平衡的。 |
-threshold <threshold> | 集群平衡的条件,datanode间磁盘使用率相差阈值,区间选择:0~100 |
-exclude -f <hosts-file> | 默认为空,指定该部分ip不参与balance |
-source -f <hosts-file> | 只选择指定的节点作为Balancer的源头 |
-include -f <hosts-file> | 默认为空,只允许该部分ip参与balance |
-idleiterations | 退出前的最大空闲迭代次数,默认为 5 |
2.2 Balancer流程
Balancer工具启动后作为一个独立的守护线程与NN分开运行,运行过程循环进行,直到集群以达到平衡状态,或者没有块可以移动,或者与NN交互报错才会停止,每次循环中的流程总体可分为以下三步:
1. 算
Balncer从NN处查询数据来计算:集器整体平均使用率,各节点的使用率,各个节点距离平衡状态可以移进或移出多少数据等。并根据计算结果将各节点分类。
2. 选
根据上一步的计算结果和分类情况,选择数据移动的源节点和目标节点对,并制作数据移动任务Task,包含了源和目标节点、移动的数据量等。
3. 移
将制作好的移动任务分发给各DN节点,等待数据移动成功,返回此次迭代的结束状态。
下面详细讲解每一步的过程:
2.3 计算并分类
在每次循环一开始Balancer客户端向NN查询集群使用情况和各节点的使用情况,以此计算集群平均使用率和各节点的使用率,再结合Balancer开始时设置的阈值,将集群分为四类分别放到四类集合中。
-
overUtilized Datanodes:过载节点,使用率超过 集群平均使用率+平衡阈值 的节点。
-
aboveAvgUtilized Datanodes:超过平均水平节点,使用率在集群平均使用率和集群平均使用率+平衡阈值之间的节点。
-
belowAvgUtilized Datanodes:低于平均水平节点,使用率在集群平均使用率-平衡阈值 和 集群平均使用率之间的节点。
-
underUtilized Datanodes:负载节点,使用率低于 集群平均使用率-平衡阈值 的节点。
2.4 选择Source和Target
根据上一步计算的结果,将四类节点分为Source和Target节点,其中Source节点包括:overUtilized、aboveAvgUtilized。 Target节点包括:belowAvgUtilized、underUtilized。再根据:
-
同NODE_GROUP (若使用)。
-
同机架。
-
其他节点。
的顺序选择<Source,Target>对。具体的顺序如下:(未使用Node Group)
-
同一机架的 overUtilized节点 到 underUtilized节点。
-
同一机架的 overUtilized节点 到 belowAvgUtilized节点,针对1中未选到的overUtilized节点。
-
同一机架的 aboveAvgUtilized节点 到 underUtilized节点,针对1中未选到的underUtilized节点。
-
其他机架的 overUtilized节点 到 underUtilized节点。
-
其他机架的 overUtilized节点 到 belowAvgUtilized节点,针对4中未选到的overUtilized节点。
-
其他机架的 aboveAvgUtilized节点 到 underUtilized节点,针对4中未选到的underUtilized节点。
经过以上6轮匹配,本次循环需要移动数据的<Source, Target>对已经匹配完成,这里的Source和Target并不是一对一的,而是多对多的,具体取决于一个节点需要移出的数据量和另一个节点可以移入的数据量。
2.6 相关参数配置
整个Balnce流程中可以通过配置调节的参数主要有以下几个:
参数 | 意义 | 默认值 |
dfs.balance.bandwidthPerSec | 用于Balancer的带宽限制 | 1M/s |
dfs.balancer.dispatcherThreads | Balancer的Dispatcher用于分发的线程池大小。dispatchExecutor | 200 |
dfs.balancer.moverThreads | 用于执行块移动的线程池大小。 moverThread | 1000 |
dfs.datanode.balance.max.concurrent.moves | Datanode中参与Balancer移动数据的最大线程数。这个值可以通过"dfsadmin -reconfig"命令重新配置。 | 50 |
dfs.balancer.getBlocks.size | 当获取源的块列表时,以字节为单位获取的Datanode块的总大小。 | 2147483648 |
dfs.balancer.getBlocks.min-block-size | 获取源的块列表时要忽略的最小块阈值大小(以字节为单位)。 | 10485760 |
dfs.balancer.block-move.timeout | 块移动的最大时间(以毫秒为单位)。如果这个值设置大于0,平衡器将在这个时间点之后停止等待块移动完成。默认为禁用(0)。 | 0 |
dfs.balancer.max-no-move-interval | 如果指定的时间已经过去,并且没有块被移出源DataNode,那么在当前的Balancer迭代中,将会花费更多的精力将块移出这个DataNode。 | 60000 |
dfs.balancer.max-size-to-move | Balancer在单个线程中可以移动的最大字节数。 | 10737418240 |
三、社区对Balancer的优化
查找社区在2.9.2版本以后合入的Balancer相关的Patch,主要有以下几个:
-
HDFS-15665 Balancer logging improvement
-
HDFS-15911 Provide blocks moved count in Balancer iteration result
-
HDFS-15438 Setting dfs.disk.balancer.max.disk.errors = 0 will fail the block copy
-
HDFS-14973 Balancer getBlocks RPC dispersal does not function properly
-
HDFS-15655 Add option to make balancer prefer to get cold blocks
-
HDFS-14894 Add balancer parameter to balance top used nodes
其中:
HDFS-15665 和 HDFS-15911是对Balancer日志和移动结果统计的优化。
HDFS-15438 解决了dfs.disk.balancer.max.disk.errors参数设为0将导致块复制失败的问题。
HDFS-14973 是对Balancer向NN发送getBlocks请求的优化。
HDFS-15655 是让Balancer优先移动冷数据,避免影响热数据的使用。
HDFS-14894 增加了一个使用参数来按照节点容量使用率来自动挑选Balancer的Source。(未合入)
该patch使用时通过指定sourceThreshold来自动确定Balancer的源节点,如:sourceThreshold设为90%以后每次循环将只选择使用率大于90%的节点作为源节点。可解决运维遇到的:将高水位节点平衡掉以后,次高水位节点又变为高水位节点的问题。但该patch状态已关闭未合入。
四、业内对Balancer的优化
经调研,eBay新增了一种基于剩余空间大小的平衡策略,解决了原有的基于节点使用率的平衡策略带来的节点剩余空间大小不平衡的问题。例如:若集群有一个10T的节点一个100T的节点,则在
基于节点使用率的平衡策略下,两节点都使用了70%为平衡状态,此时一个节点使用了7T剩余3T,另一个节点使用了70T,剩余30T,显然我们更希望100T的节点存放更多的数据。
若是在在基于剩余空间大小的平衡策略下,这两个节点将被最终平衡到都只剩下3T的状态,其追求的是节点有一样的剩余空间。
这种平衡策略除了在第一步计算的时候与原策略不同以外,其他的过程没有改变。