实验环境
机架感知
一个hadoop分布式集群会有很多的服务器,由于受到机架槽位和交换机网口的限制,通常大型的分布式集群都会跨好几个机架,机架内的服务器之间的网络速度通常都会高于跨机架服务器之间的网络速度,并且机架之间服务器的网络通信通常受到上层交换机间网络带宽的限制。
HDFS对数据文件是分block存储,每个block默认有3个副本(也可以配置大于3),HDFS对副本的存放策略如下:
- 第一个block副本放在和client所在的node里(如果client不在集群范围内,则这第一个node是随机选取的)。
- 第二个副本放置在与第一个节点不同的机架中的node中(随机选择)。
- 第三个副本放置在与第一个副本所在节点同一机架的另一个节点上。
- 如果还有更多的副本则随机放在集群的node里。
这样的策略主要是为了数据的可靠性和数据访问的性能考虑。
- 数据分布于不同的机架上,就算整个机架挂掉后,其他机架上还有冗余备份,整个集群依然能对外服务。
- 数据分布于不同的机架上,运行mapreduce任务时可以就近获取所需的数据。
hadoop对机架的感知并非是自适应的,而是需要使用者告诉hadoop机器(ip)与机架的对应关系。
实现
hadoop机架感知可以有两种方式实现,编写机架感知程序和脚本方式。
机架感知程序
实现接口DNSToSwitchMapping
import org.apache.hadoop.net.DNSToSwitchMapping; import java.util.ArrayList; import java.util.List; public class MyDNSToSwitchMapping implements DNSToSwitchMapping { @Override public List<String> resolve(List<String> list) { List<String> paths = new ArrayList<String>(); if (list != null && !list.isEmpty()) { for (String hostname : list) { String rackPath = ""; if ("master".equals(hostname)) { //以主机名来判断,实验环境中只有master和slave1。 rackPath = "/rack1"; } else { rackPath = "/rack2"; } paths.add(rackPath); } } return paths; } @Override public void reloadCachedMappings() { } @Override public void reloadCachedMappings(List<String> list) { } }
pom.xml
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.6.5</version> </dependency>
将上述代码打包,上传到master节点hadoop根目录share/hadoop/common/lib下。
mvn package -Dmaven.test.skip=true
修改core-site.xml配置。
<property> <name>net.topology.node.switch.mapping.impl</name> <value>com.tongfang.learn.MyDNSToSwitchMapping</value> <!-- 根据实际的类全路径(加上包名)配置--> </property>
将jar包和修改的配置分发到slave1节点上,重新启动节点
./sbin/start-dfs.sh
查看集群机器分布情况
[hadoop@master hadoop-2.6.5]$ ./bin/hdfs dfsadmin -printTopology Rack: /rack1 192.168.1.160:50010 (master) Rack: /rack2 192.168.1.161:50010 (slave1)
可以看出机器分布于rack1和rack2两个机架。
脚本
hadoop也提供了脚本的方式来配置机架感知方式,常见的实现方式有shell脚本和python脚本两种方式,这里以python脚本为例。
编写感知脚本,并授予执行权限。
#!/usr/bin/python #coding=utf-8 import sys rack={ "192.168.1.160":"/dc1/rack1", "192.168.1.161":"/dc1/rack2", "master":"/dc1/rack1", "slave1":"/dc1/rack2", } if __name__=="__main__": print rack.get(sys.argv[1], "default-rack") #主机名或ip不存在,则使用默认机架default-rack
由于没有找到确切的文档说明 到底是主机名还是ip地址会被传入到脚本,所以在脚本中最好兼容主机名和ip地址。
添加执行权限:
chmod +x test.py
在master上修改core-site.xml配置。
<property> <name>net.topology.script.file.name</name> <value>/home/hadoop/test.py</value> <!-- 根据脚本实际路径配置 --> </property
将脚本和修改的配置分发到slave1上,并重启集群
./sbin/start-dfs.sh
查看集群机器分布情况。
[hadoop@master hadoop-2.6.5]$ ./bin/hdfs dfsadmin -printTopology Rack: /dc1/rack1 192.168.1.160:50010 (master) Rack: /dc1/rack2 192.168.1.161:50010 (slave1)
可以看出机器分布于 /dc1/rack1和/dc1/rack2两个机架。