Hadoop数据倾斜,快速精确balance的方法

Hadoop集群Datanode数据倾斜,个别节点hdfs空间使用率达到95%以上,于是新增加了三个Datenode节点,由于任务还在跑,数据在不断增加中,这几个节点现有的200GB空间估计最多能撑20小时左右,所以必须要进行balance操作。

首先执行了一下balance操作:

[hdfs@sudops.com hadoop] $sh start-balancer.sh -threshold 5

通过观察磁盘使用情况,发现balance的速度明显跟不上新增数据的速度,这明显是药丸啊。。。!!!

跟踪了一下balance的日志,发现两个问题:
一是balance时原有的十几个节点都被列入了待balance的节点中,上面的数据分块移动到新增加的3个节点上,由于节点多,最迫切需要balance的几个节点轮到的机会很少;
二是balance的速度太慢了,Hadoop集群为了防止balance影响吞吐、I/O性能,默认balance的速度为1MB,这样一共8TB的数据需要balance,这需要太长时间了。

于是针对上述问题,进行了如下尝试:

    提高blance的速度,将默认的balance速度从1MB/s增大到50MB/s
#set balance to 50M/s
[hdfs@sudops.com hadoop]$ hdfs dfsadmin -setBalancerBandwidth 52428800
Balancer bandwidth is set to 52428800 for nn01.sudops.com/10.233.100.161:9000
Balancer bandwidth is set to 52428800 for nn02.sudops.com/10.233.100.162:9000
    调整balance的平衡比例:

将原来的%5 提高到20%,调整原则就是尽量先让balance影响到最需要平衡数据的节点。

简单说明一下:原有集群的hdfs占用率为80%,新增加3个节点后,集群hdfs的整体占用量为70%, 如果比例是%5的话,那么原有节点都在这个调整范围内,所以各个节点都要被balance,而接受balance的节点只有三个,所以轮到迫切需要balance的节点的概率就比较小;
如果调整到20%,那么原来使用量小于90%的节点都不会被balance,那几台占用量90%以上的节点才会被最先balance,这样只有3个节点符合这个条件,balance的精确性就高了很多。

综合以上两点,balance的效果好多了,解决了最紧迫的节点的磁盘占满的问题,balance的速度终于快于新增数据,20%时需要balance的数据为6TB左右,待这次balance结束后,再运行一次%5的balance,还有2TB的数据要balance,这样经过两次的balance的操作,集群基本平衡了。

第一次balance前各各节点情况:

DFS Used%: 70.08%
DFS Used%: 85.67%
DFS Used%: 80.70%
DFS Used%: 9.37%
DFS Used%: 80.72%
DFS Used%: 79.31%
DFS Used%: 81.36%
DFS Used%: 90.13%
DFS Used%: 8.97%
DFS Used%: 81.81%
DFS Used%: 80.69%
DFS Used%: 87.68%
DFS Used%: 80.82%
DFS Used%: 2.57%
DFS Used%: 70.25%

第一次balance:

[hdfs@sudops.com hadoop]$ sh start-balancer.sh -threshold 20
日志:
2016-11-11 08:11:17,537 INFO org.apache.hadoop.hdfs.server.balancer.Balancer: 3 over-utilized: [datanode01:50010:DISK, datanode02:50010:DISK, datanode03:50010:DISK]
2016-11-11 08:11:17,537 INFO org.apache.hadoop.hdfs.server.balancer.Balancer: 3 underutilized: [datanode13:50010:DISK, datanode14:50010:DISK, datanode15:50010:DISK]
2016-11-11 08:11:17,537 INFO org.apache.hadoop.hdfs.server.balancer.Balancer: Need to move 6.86 TB to make the cluster balanced.

第一次balance结束:

Time Stamp               Iteration#  Bytes Already Moved  Bytes Left To Move  Bytes Being Moved
   1 Time Stamp               Iteration#  Bytes Already Moved  Bytes Left To Move  Bytes Being Moved
   2 Nov 11, 2016 8:16:38 AM           0              6.66 GB             6.08 TB              30 GB
   3 Nov 11, 2016 8:18:21 AM           1             11.34 GB             6.07 TB              30 GB
   4 Nov 11, 2016 8:19:00 AM           2             11.54 GB             6.06 TB              30 GB
...   
1520 Nov 12, 2016 10:49:44 PM       1517              6.05 TB                 0 B               -1 B
1521 Nov 12, 2016 10:49:44 PM Balancing took 38.58443388888889 hours

现在最近紧迫的几个几点已经被balance了,继续进行。。
第二次balance:

[hdfs@sudops.com hadoop]$ sh start-balancer.sh -threshold 5

第二次balance结束:

   1 Time Stamp               Iteration#  Bytes Already Moved  Bytes Left To Move  Bytes Being Moved
   2 Nov 13, 2016 10:11:40 AM          0              1.59 GB             2.32 TB           33.31 GB
   3 Nov 13, 2016 10:12:31 AM          1              3.81 GB             2.32 TB           32.19 GB
   4 Nov 13, 2016 10:13:10 AM          2              4.76 GB             2.31 TB           30.67 GB
...   
1240 Nov 14, 2016 9:36:48 AM        1238              2.40 TB           272.99 MB              10 GB
1241 The cluster is balanced. Exiting...
1242 Nov 14, 2016 9:36:57 AM        1239              2.40 TB                 0 B               -1 B
1243 Nov 14, 2016 9:36:57 AM  Balancing took 23.432305555555555 hours

第二次balance后各节点情况,集群已经基本平衡了:

DFS Used%: 70.77%
DFS Used%: 68.80%
DFS Used%: 67.66%
DFS Used%: 62.45%
DFS Used%: 66.87%
DFS Used%: 66.83%
DFS Used%: 66.88%
DFS Used%: 68.91%
DFS Used%: 62.34%
DFS Used%: 69.55%
DFS Used%: 66.95%
DFS Used%: 71.81%
DFS Used%: 66.87%
DFS Used%: 62.20%
DFS Used%: 66.86%

其实操作起来非常简单,只需要两条命令即可。

网上也有同学说可以让某个hdfs空间最满的节点先做下线处理,做下decommission,格式化现有的数据盘,然后再重新加入到节点中来,这也是个方法,让hdfs缺失的一份数据平均分配到其他节点上,速度会比较快,不过我担心有些许风险,并没有采用。