实战!HDFS集群负载不均衡问题
Posted 柚子聊大数据
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实战!HDFS集群负载不均衡问题相关的知识,希望对你有一定的参考价值。
背景环境说明
某项目现场HDFS集群有五台机器,其中两台机器分别部署NameNode、SecondNameNode,另外三台机器部署DataNode节点(这里就不吐槽这种部署方式了)。
由于历史原因,DataNode A、DataNode B机器的/data01、/data02、/data03均为8T,DataNode C机器的/data01、/data02均小于1T,/data03为8T。
在使用了一段时间后,问题突显了——DataNode C上的/data01、/data02磁盘使用率将近70%,剩余所有8T的盘利用率均小于7%,若不及时处理,这两块较小的磁盘使用率达到100%时,那整个hdfs集群就不可用了。
说明:
该现场使用的是CDH HDFS 2.6.0版本。
解决过程
方案一、修改磁盘选择策略
HDFS 2.X 版本将数据写入磁盘时,有两种策略——基于轮询的策略、基于可用空间的策略。默认情况下采用的是基于轮询的策略。
基于轮询的策略,即每次写入都会采用轮询的方式,由于每次写入的数据量不一致,且这套环境大小磁盘差距这么大,更容易出现磁盘利用率相差很大的现象。
基于可用空间的策略,在这里策略之下,会计算出可用磁盘空间,磁盘空间大的,写入的概率会更大,这在一定程度上减少了磁盘利用率的差距。
修改方式,打开hdfs-site.xml,修改如下配置项:
配置项 |
配置值 |
dfs.datanode.fsdataset.volume.choosing.policy | org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy |
dfs.datanode.available-space-volume-choosing-policy.balanced-space-threshold | 默认值10G。当磁盘中最大可用空间与最小可用空间的差值小于这个阈值,则认为存储是平衡的,直接采用轮询来选择卷。 |
dfs.datanode.available-space-volume-choosing-policy.balanced-space-preference-fraction | 默认值0.75。它的含义是数据块存储到可用空间多的卷上的概率。 |
根据上述配置项的含义,可以知道修改磁盘写入策略,并不能解决该问题,磁盘在剩余10G以前,都是采用轮询的方式,小磁盘利用率很快就使用的很高。
方案二、HDFS Balancer
在其他的现场,也曾出现过datanode数据倾斜,导致Spark任务运行时,各种网络开销,资源使用差距大的情况。此种情况下,我司使用HADOOP提供的start-balancer.sh脚本,使用方式如下:
首先,修改hdfs-site.xml中网络带宽限制,默认1MB/s,此处改为100MB/s。
<property>
<name>dfs.balance.bandwidthPerSec</name>
<value>104857600</value>
</property>
其次,启动数据均衡,阈值 5%
bin/start-balancer.sh -threshold 5
可惜的是,在该场景下使用start-balancer.sh后,发现这两块小磁盘的使用率并没有减少,并发现从DataNode层面来看,数据存储是均匀的。于是乎我就查了相关的资料,我的猜想得到了证实——start-balancer.sh只能用于datanode之间的负载均衡,做不到磁盘间的负载均衡。
方案三、disk balancer
该方案仅限于Hadoop 3.x版本,对于本项目的CDH HDFS 2.6版本,并不适用。
HDFS 磁盘均衡器在DataNode中以线程的形式运行,并在相同存储类型的卷之间移动数据。这与方案二中start-balancer.sh不同,start-balancer.sh作用于datanode之间的负载均衡。
使用方式如下:
首先,修改所有datanode节点的hdfs-site.xml
dfs.disk.balancer.enabled设置为true
其次,获取本DataNode的信息,并用如下命令生成执行计划
hdfs diskbalancer -plan 主机名
接着,执行磁盘均衡器脚本
hdfs diskbalancer -execute /plan.json
最后,可以用如下命令查看disk balancer的执行进度
hdfs diskbalancer -query 主机名:20001
方案四、卸掉小磁盘
上述三种方案对于我这种场景都不适用,现场项目经理也协调不到更多的磁盘,目前我给出的方案就是卸掉这两块小磁盘,延缓出现木桶效应。
去掉小盘的方式,也很简单,就两步骤。
其一,停止datanode节点。
其二,修改hdfs-site.xml,将dfs.datanode.data.dir中的小磁盘路径去掉。
最后,重启datanode节点即可。
在这个方案实施过程中,我还发现两个问题。
问题一、停止datanode后,在50070页面上并未直接反应出该datanode已下线。
namenode感知到datanode下线时间,由这两个配置项决定。
<property>
<name>dfs.heartbeat.interval</name>
<value>3</value>
<description>Determines datanode heartbeat interval in seconds.</description>
</property>
<property>
<name>dfs.namenode.heartbeat.recheck-interval</name>
<value>300000</value>
<description>The unit of this configuration is millisecond.</description>
</property>
具体公式
2*dfs.namenode.heartbeat.recheck-interval+10*dfs.heartbeat.interval
所以默认下线时间为10分30秒。
问题二、重启datanode后,再次登录hdfs 50070页面,会发现可能有块丢失,具体告警信息如下:
There are 2 missing blocks. The following files may be corrupted:
blk_123456 /user/part-c000.snappy.parquet
理论上,hdfs 文件是三副本的,为啥卸掉一块盘会出现块丢失呢?
经查看,这些文件都是单副本的。所以这种卸载磁盘的方式确实会导致单副本文件丢失。
[zsf@zsf166 logs]$ hdfs dfs -ls /user/zsf
Found 152 items
-rwxrwxrwx 1 rhino supergroup 70296 2019-10-25 16:21 /user/zsf/__spark_conf__.zip
-rwxrwxrwx 1 rhino supergroup 20195 2019-10-25 16:21 /user/zsf/annotations-12.0.jar
-rwxrwxrwx 1 rhino supergroup 95536 2019-10-25 16:21 /user/zsf/apache-mime4j-core-0.7.2.jar
总结
1、基于轮询、基于可用空间的写入磁盘策略,不能避免负载不均匀现象的发生。
2、start-balancer.sh从DataNode层面来均衡负载。disk balancer在DataNode内部的磁盘间达到负载均衡。
3、对于低版本HDFS,只能通过一块块的卸载小磁盘来避免小磁盘带来的影响。
参考链接
1、http://mp.weixin.qq.com/s?__biz=MzI4OTY3MTUyNg==&mid=2247489557
&idx=1&sn=65ff210ef504b82aee1435a0ae142747&scene=6#wechat_redirect
2、https://www.cnblogs.com/roger888/p/5504586.html
3、https://www.jianshu.com/p/d0c59d874dfd
4、https://www.jianshu.com/p/f7c1cd476601
5、https://my.oschina.net/u/3197158/blog/1601649
以上是关于实战!HDFS集群负载不均衡问题的主要内容,如果未能解决你的问题,请参考以下文章