深入浅出:Hadoop的start-balancer.sh与hdfs balancer分布式数据均衡

Hadoop的HDFS集群非常容易出现机器与机器之间磁盘利用率不平衡的情况,比如集群中添加新的数据节点。当HDFS出现不平衡状况的时候,将引发很多问题,比如:
1、MR程序无法很好地利用本地计算的优势
2、机器之间无法达到更好的网络带宽使用率,机器磁盘无法利用等等。可见,保证HDFS中的数据平衡是非常重要的。
在Hadoop中,包含一个Balancer程序,通过运行这个程序,可以使得HDFS集群达到一个平衡的状态,使用这个程序的命令如下:

$HADOOP_HOME/bin/start-balancer.sh –t 10%

这个命令中-t参数后面跟的是HDFS达到平衡状态的磁盘使用率偏差值。如果机器与机器之间磁盘使用率偏差小于10%,那么我们就认为HDFS集群已经达到了平衡的状态。
Hadoop的开发人员在开发Balancer程序的时候,遵循了以下几点原则:
1.在执行数据重分布的过程中,必须保证数据不能出现丢失,不能改变数据的备份数,不能改变每一个rack中所具备的block数量。(这个原则导致了不同rack机柜之间的数据是不能移动的
2.系统管理员可以通过一条命令启动数据重分布程序或者停止数据重分布程序。
3.Block在移动的过程中,不能暂用过多的资源,如网络带宽。
4.数据重分布程序在执行的过程中,不能影响name node的正常工作。

集群执行balancer依旧不平衡的原因
基于这些基本点,目前Hadoop数据重分布程序实现的逻辑流程如下图所示:

Name Node <------------------------------->Rebalancing Server<-------------------------------->Proxy source data node
/| /|\

|                                                                                                 |
|                                                                                                 |
+----------------------------------->destination data node<---------------------------------------+

Rebalance程序作为一个独立的进程与name node进行分开执行。
1 Rebalance Server从Name Node中获取所有的Data Node情况:每一个Data Node磁盘使用情况。
2 Rebalance Server计算哪些机器需要将数据移动,哪些机器可以接受移动的数据。并且从Name Node中获取需要移动的数据分布情况。
3 Rebalance Server计算出来可以将哪一台机器的block移动到另一台机器中去。
4,5,6 需要移动block的机器将数据移动的目的机器上去,同时删除自己机器上的block数据。
7 Rebalance Server获取到本次数据移动的执行结果,并继续执行这个过程,一直没有数据可以移动或者HDFS集群以及达到了平衡的标准为止。

Hadoop现有的这种Balancer程序工作的方式在绝大多数情况中都是非常适合的。
现在我们设想这样一种情况:
1 数据是3份备份。
2 HDFS由2个rack(机柜)组成。
3 2个rack中的机器磁盘配置不同,第一个rack(机柜)中每一台机器的磁盘空间为1TB,第二个rack(机柜)中每一台机器的磁盘空间为10TB。
4 现在大多数数据的2份备份都存储在第一个rack(机柜)中。
在这样的一种情况下,HDFS级群中的数据肯定是不平衡的。现在我们运行Balancer程序,但是会发现运行结束以后,整个HDFS集群中的数据依旧不平衡:rack1中的磁盘剩余空间远远小于rack2。这是因为Balance程序的开发原则1导致的。
简单的说,就是在执行Balancer程序的时候,不会将数据中一个rack(机柜)移动到另一个rack中(机柜),所以就导致了Balancer程序永远无法平衡HDFS集群的情况。
针对于这种情况,可以采取2中方案:
1 继续使用现有的Balancer程序,但是修改rack中的机器分布。将磁盘空间小的机器分叉到不同的rack中去。
2 修改Balancer程序,允许改变每一个rack中所具备的block数量,将磁盘空间告急的rack中存放的block数量减少,或者将其移动到其他磁盘空间富余的rack中去。(不推荐)

1.传输带宽
对hdfs负载设置均衡,因为默认的数据传输带宽比较低,可以设置为64M,
即hdfs dfsadmin -setBalancerBandwidth 67108864即可

[root@sht-sgmhadoopnn-01 ~# cd /hadoop/hadoop-2.7.2/bin
[root@sht-sgmhadoopdn-01 bin# ./hdfs dfsadmin -setBalancerBandwidth 67108864
Balancer bandwidth is set to 67108864 for sht-sgmhadoopnn-01/172.16.101.55:8020
Balancer bandwidth is set to 67108864 for sht-sgmhadoopnn-02/172.16.101.56:8020

2.节点存储使用率偏差
默认balancer的threshold为10%,即各个节点存储使用率偏差不超过10%,我们可将其设置为5%;然后启动Balancer,sbin/start-balancer.sh -threshold 5,等待集群自均衡完成即可

[root@sht-sgmhadoopdn-01 bin# cd ../sbin
starting balancer, logging to /hadoop/hadoop-2.7.2/logs/hadoop-root-balancer-sht-sgmhadoopnn-01.telenav.cn.out
[root@sht-sgmhadoopnn-01 sbin# ./start-balancer.sh -threshold 5
starting balancer, logging to /hadoop/hadoop-2.7.2/logs/hadoop-root-balancer-sht-sgmhadoopnn-01.telenav.cn.out

运行这个命令start-balancer.sh -threshold 5和使用hdfs balancer -threshold 5是一样的

Usage: hdfs balancer

[root@sht-sgmhadoopnn-01 bin# ./hdfs balancer -threshold 5
16/03/05 18:57:33 INFO balancer.Balancer: Using a threshold of 1.0
16/03/05 18:57:33 INFO balancer.Balancer: namenodes = [hdfs://mycluster
16/03/05 18:57:33 INFO balancer.Balancer: parameters = Balancer.Parameters[BalancingPolicy.Node, threshold=1.0, max idle iteration = 5, number of nodes to be excluded = 0, number of nodes to be included = 0
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
16/03/05 18:57:34 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
16/03/05 18:57:35 INFO net.NetworkTopology: Adding a new node: /default-rack/172.16.101.58:50010
16/03/05 18:57:35 INFO net.NetworkTopology: Adding a new node: /default-rack/172.16.101.60:50010
16/03/05 18:57:35 INFO net.NetworkTopology: Adding a new node: /default-rack/172.16.101.66:50010
16/03/05 18:57:35 INFO net.NetworkTopology: Adding a new node: /default-rack/172.16.101.59:50010
16/03/05 18:57:35 INFO balancer.Balancer: 0 over-utilized: [
16/03/05 18:57:35 INFO balancer.Balancer: 0 underutilized: [
The cluster is balanced. Exiting...
Mar 5, 2016 6:57:35 PM 0 0 B 0 B -1 B
Mar 5, 2016 6:57:35 PM Balancing took 2.66 seconds

1).为什么我执行该命令hdfs balancer -threshold 5平衡数据命令没有反应呢?5表示5%,

群总存储使用率: 1.74%
sht-sgmhadoopdn-01: 1.74%
sht-sgmhadoopdn-02: 1.74%
sht-sgmhadoopdn-03: 1.74%
sht-sgmhadoopdn-04: 0%
执行-threshold 5, 表示每一个 datanode 存储使用率和集群总存储使用率的差值都应该小于这个阀值5%;
假如超过5%,会执行数据平衡操作。

B. 2).怎样判断执行命令是否会生效,数据平衡操作?

if (群总存储使用率 — 每一台datanode 存储使用率) > -threshold 5

  #会执行数据平衡

else

  #该命令不生效

end if
C. 3).the threshold range of [1.0, 100.0],所以最小只能设置 -threshold 1

D. 4).balance命令可以执行早namenode或者datanode节点上

  1. 执行命令hdfs balancer -threshold 2
    点击(此处)折叠或打开

[root@sht-sgmhadoopnn-01 hadoop# hdfs balancer -threshold 2
……………..
……………..
16/03/08 16:08:09 INFO net.NetworkTopology: Adding a new node: /default-rack/172.16.101.59:50010
16/03/08 16:08:09 INFO net.NetworkTopology: Adding a new node: /default-rack/172.16.101.58:50010
16/03/08 16:08:09 INFO net.NetworkTopology: Adding a new node: /default-rack/172.16.101.66:50010
16/03/08 16:08:09 INFO net.NetworkTopology: Adding a new node: /default-rack/172.16.101.60:50010
16/03/08 16:08:09 INFO balancer.Balancer: 0 over-utilized: [
16/03/08 16:08:09 INFO balancer.Balancer: 0 underutilized: [
The cluster is balanced. Exiting...
Mar 8, 2016 4:08:09 PM 1 382.22 MB 0 B -1 B
Mar 8, 2016 4:08:09 PM Balancing took 6.7001 minutes

新增数据节点的411.7M,偏差小于2%。

start-balancer.sh和stop-balancer.sh的源码解析:

[root@sht-sgmhadoopnn-01 sbin]# more start-balancer.sh

!/usr/bin/env bash

bin=dirname "${BASH_SOURCE-$0}"
bin=cd "$bin"; pwd
DEFAULT_LIBEXEC_DIR="$bin"/../libexec
HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
. $HADOOP_LIBEXEC_DIR/hdfs-config.sh

Start balancer daemon.

"$HADOOP_PREFIX"/sbin/hadoop-daemon.sh --config $HADOOP_CONF_DIR --script "$bin"/hdfs start balancer $@
解析:start-balancer.sh脚本其实最终还是调用hdfs start balancer $@ 命令,对于 $@ 是指shell脚本运行的传递的参数列表,一般参数为-threshold 5

[root@sht-sgmhadoopnn-01 sbin# more stop-balancer.sh

!/usr/bin/env bash

bin=dirname "${BASH_SOURCE-$0}"
bin=cd "$bin"; pwd
DEFAULT_LIBEXEC_DIR="$bin"/../libexec
HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
. $HADOOP_LIBEXEC_DIR/hdfs-config.sh

Stop balancer daemon.

Run this on the machine where the balancer is running

"$HADOOP_PREFIX"/sbin/hadoop-daemon.sh --config $HADOOP_CONF_DIR --script "$bin"/hdfs stop balancer
解析:stop-balancer.sh脚本其实最终还是调用hdfs stop balancer命令
[root@sht-sgmhadoopnn-01 sbin#

注意事项:
由于历史原因,hadoop集群中的机器的磁盘空间的大小各不相同,而HDFS在进行写入操作时,并没有考虑到这种情况,所以随着数据量的逐渐增加,磁盘较小的datanode机器上的磁盘空间很快将被写满,从而触发了报警。
此时,不得不手工执行start-balancer.sh来进行balance操作,即使将dfs.balance.bandwidthPerSec 参数设置为10M/s,整个集群达到平衡也需要很长的时间,所以写了个crontab来每天凌晨来执行start-balancer.sh,由于此时集群不平衡的状态还没有那么严重,所以start-balancer.sh很快执行结束了。
另外需要注意的地方是,由于HDFS需要启动单独的Rebalance Server来执行Rebalance操作,所以尽量不要在NameNode上执行start-balancer.sh,而是找一台比较空闲的机器。
理论参考:http://www.aboutyun.com/thread-7354-1-1.html

上一篇:Cloudera-manager(CDH6.3.0)大数据平台搭建一指禅(impala,kudu,hdfs,hive,kafka,yarn,spark,hbase,hue)


下一篇:Hadoop机架感知(rack-aware)配置指南