Hadoop版本:2.9.2
通常大型 Hadoop 集群是以机架的形式来组织的,同一个机架上的不同节点间的网络状况比不同机架之间的更为理想,NameNode 设法将数据块副本保存在不同的机架上以提高容错性。
(资料图)
HDFS 不能够自动判断集群中各个 DataNode 的网络状况情况,Hadoop 允许集群的管理员通过配置 net.topology.script.file.name 参数来确定节点所处的机架,配置文件提供了 ip 到 rackid 的翻译。NameNode 通过这个配置知道集群中各个 DataNode 机器的 rackid。如果 net.topology.script.file.name 没有设定,则每个 ip 都会被翻译成 /default-rack。机器感知如下图所示:
图中的 D 和 R 是交换机,H 是 DataNode,则 H1 的 rackid = /D1/R1/H1,有了 rackid 信息(这些 rackid 信息可以通过 net.topology.script.file.name 配置)就可以计算出任意两台 DataNode 之间的距离。
distance(/D1/R1/H1 , /D1/R1/H1) = 0 相同的 DataNodedistance(/D1/R1/H1 , /D1/R1/H2) = 2 同 rack 下的不同 DataNodedistance(/D1/R1/H1 , /D1/R2/H4) = 4 同 IDC 下的不同 DataNodedistance(/D1/R1/H1 , /D2/R3/H7) = 6 不同 IDC 下的 DataNode说明:
当没有配置机架信息时,所有的机器 Hadoop 都在同一个默认的机架下,名为 "/defult-rack",这种情况的任何一台 DataNode 机器,bug物理上是否属于同一个机架,都会被认为是在同一个机架下。一旦配置 net.topology.script.file.name,就按照网络拓扑结构来寻找 DataNode:net.topology.script.file.name 这个配置选项的 value 指定为一个可执行程序,通常为一个脚本。默认情况下,hadoop 的机架感知是没有被启用的。所以,在通常情况下,hadoop 集群的 HDFS 在选机器的时候,是随机选择的。也就是说,如果实际节点不完全在相同的机架,但是又没有配置机架感知很有可能在写数据时:
hadoop 将第一块数据 block1 写到了 rack1 上,然后随机的选择下将 block2 写入到了 rack2 下,此时两个 rack 之间产生了数据传输的流量,再接下来,在随机的情况下,又将 block3 重新又写回了 rack1,此时,两个 rack 之间又产生了一次数据流量。在 job 处理的数据量非常的大,或者往 hadoop 推送的数据量非常大的时候,这种情况会造成 rack 之间的网络流量成倍的上升,成为性能的瓶颈,进而影响作业的性能以至于整个集群的服务。
不同节点之间的通信能够尽量发生在同一个机架之内,而不是跨机架;
为了提高容错能力,DataNode 会尽可能把数据块的副本放到多个机架上。
执行hdfs dfsadmin -printTopology打印当前机架信息,可以看到默认所有节点都是一个机架 default-rack,此时没有配置机架感知。
hdfs dfsadmin -printTopology
新建机架配置文件topology.data
vim $HADOOP_HOME/topology.data
由于官方配置文件没有确切的说明到底是主机名还是 ip 地址会被传入到脚本,所以在脚本中最好兼容主机名和 ip 地址。
192.168.166.121 hadoop1 /switch1/rack1192.168.166.122 hadoop2 /switch1/rack1192.168.166.123 hadoop3 /switch1/rack2
在Hadoop的安装目录下新建脚本topology.sh
vim $HADOOP_HOME/topology.sh
编写脚本内容
#!/bin/bash# 此处是你的机架配置文件topology.sh所在目录HADOOP_CONF=/opt/servers/hadoopwhile [ $# -gt 0 ] ;do #脚本第一个参数节点ip或者主机名称赋值给nodeArg nodeArg=$1 #以只读的方式打开机架配置文件 exec<${HADOOP_CONF}/topology.data #声明返回值临时变量 result="" #开始逐行读取 while read line do #赋值行内容给ar,通过这种 变量=( 值 )的方式赋值,下面可以通过数组的方式取出每个词 ar=( $line ) #判断输入的主机名或者ip是否和该行匹配 if [ "${ar[0]}" = "$nodeArg" ]||[ "${ar[1]}" = "$nodeArg" ] then #将机架信息赋值给result result="${ar[2]}" fi done shift #-z判断字符串长度是否为0,不为0输出实际机架,为0返回默认机架信息 if [ -z "$result" ] then echo -n "/default-rack" else echo -n "$result" fidone
脚本必须添加可执行权限
chmod 777 topology.sh
修改 core-site.xml 文件。
net.topology.script.file.name /opt/servers/hadoop/topology.sh
rsync-script etc/hadoop/core-site.xmlrsync-script topology.*
重启集群,执行 hdfs dfsadmin -printTopology 打印机架信息,可以看到集群已经按照配置感应到节点机架位置。
hdfs dfsadmin -printTopology
测试上传文件,因为只搭建了三个节点,因此设置副本数为2,查看两个副本是否存在不同的机架rack1和rack2上的节点。
在 hadoop2.8 版本之前的版本上述的结论可能不同,主要跟 Hadoop 的副本策略有关,详细的副本策略请看 https://weixiaodyanlei.xyz/archives/hdfs-fu-ben-ji-zhi
hdfs dfs -D dfs.replication=2 -put LICENSE.txt /
可以通过如下命令查看 HDFS 中的文件所在机架
hdfs fsck /LICENSE.txt -blocks -files -locations -racks