版本:Apache Hadoop 1.0.3
Hadoop集群节点通常会跨很多个机架,增加节点的情况时有发生,而且很多时候节点的磁盘容量还不统一,有大有小,所以集群节点非常容易出现磁盘利用不平衡的情况,一些节点的磁盘快用光了,另外一些节点磁盘容量还剩余很多。这会导致一些问题,首先是一些机器磁盘读写很频繁,另外一些机器很闲;MR任务分配到一个没有相应数据块的节点上时,需要从其它机器上拿数据,占用大量的网络带宽,又拖慢了任务执行的时间。
如何尽量避免这些情况的发生呢?首先要配置机架感知,把一部分数据分配到其它机架内的节点上;即使这样还不够,仍然会出现不数据存放不平衡的现象,我们还需要balancer。
balancer的话,可以使用命令bin/start-balancer.sh -threshold N。
balancer过程有点复杂,但是有一点,再平衡时会优先考虑同一机架内的节点。例如有两个机架,机架1和机架2,其中节点A位于机架1内,当集群再平衡时,系统会优先把节点A的数据块平衡到机架1中的其它节点,而不是机架2的节点。这样,当再平衡结束时,会导致数据块在整个HDFS集群中的分布仍然不平衡。所以在建设Hadoop集群时应该考虑到这个情况,最好把磁盘容量大的节点和磁盘容量小的节点混合安排进一个机架。
我们重点来看机架感知。
Hadoop在设计时考虑到数据的安全与高效,数据文件默认在HDFS上存放三份,存储策略为本地一份,同机架内其它某一节点上一份,不同机架的某一节点上一份。这样如果本地数据损坏,节点可以从同一机架内的相邻节点拿到数据,速度肯定比从跨机架节点上拿数据要快;同时,如果整个机架的网络出现异常,也能保证在其它机架的节点上找到数据。
那么Hadoop是如何确定任意两个节点是位于同一机架,还是跨机架的呢?答案就是机架感知。
HDFS集群在启动时会检查机架感知配置,根据配置对节点进行一次扫描转换,得到节点的机架ID,相同ID的节点肯定位于同一机架。问题是,Hadoop并不能智能识别节点位于哪个机架,它需要我们告诉集群哪些节点属于哪些机架,然后集群才能得到这些节点的机架ID。我们需要配置一下,使机架感知生效。
在core-site.xml中有一个参数,topology.script.file.name,该参数通常指定一个脚本,用来输出节点与机架的对应关系。最简单的示例是hadoop wiki中的一个脚本,参考:。
#!/bin/bash
HADOOP_CONF=/etc/hadoop/conf
while [ $# -gt 0 ] ; do
nodeArg=$1
exec< ${HADOOP_CONF}/topology.data
result=""
while read line ; do
ar=( $line )
if [ "${ar[0]}" = "$nodeArg" ] ; then
result="${ar[1]}"
fi
done
shift
if [ -z "$result" ] ; then
echo -n "/default/rack "
else
echo -n "$result "
fi
done
topology.data的格式为:节点(ip或主机名) /交换机xx/机架xx
需要注意的是,在Namenode上,该文件中的节点必须使用IP,使用主机名无效,而Jobtracker上,该文件中的节点必须使用主机名,使用IP无效。这经过了本人的亲自试验。