视图文件系统(View File System ,ViewFs)提供了管理多个Hadoop文件系统命名空间的方式,该系统在HDFS联盟的集群中有多个NameNode(因此有多个命名空间)是特别有用。ViewFs与某些Linux或Unix系统的客户端挂载表类似,可以被用于创建个性化的命名空间视图和整个集群共同的视图。本篇文章基于拥有几个集群,集群互相联合形成多个命名空间的Hadoop系统,也学习了在HDFS联盟中使用ViewFs提供整个集群的全局命名空间,这样应用程序可以以与在联盟中相似的方式操作。
在HDFS联盟出现之前(也就是hadoop-1.x中),整个集群中只有单一的NameNode,该NameNode为集群提供了单一的文件系统命名空间。假设存在多个集群,每个集群的文件系统命名空间是完全独立和不相交的,而且集群间不共享物理存储,比如集群间不共享DataNodes。每个集群中的core-site.xml设置了该集群中NameNode的默认文件系统:
<property> <name>fs.default.name</name> <value>hdfs://namenodeOfClusterX:port</value> </property>
该配置参数允许使用以斜线开头的相对路径,并将该路径解析为相对NameNode的路径,例如/foo/bar解析为hdfs://namenodeOfClusterX:port/foo/bar。该参数设置在集群中的每个网关和关键服务中,如JobTracker。在上述配置的集群中,典型的路径名如下:
distcp hdfs://namenodeClusterY:port/pathSrc hdfs://namenodeClusterZ:port/pathDest
在一个集群中建议使用第一种类型的路径名,也就是相对路径,而不是全限定URI,如第二种路径。
在Hadoop-2.x中出现了HDFS联盟,允许一个集群中存在多个NameNode,因此上述路径名的使用方式也发生了变化。假设存在多个集群,每个集群有一个或者多个NameNode,每个NameNode拥有自己的命名空间,且只属于一个集群,相同集群中的NameNode共享集群的物理存储,集群间的命名空间彼此独立。根据存储的需要,操作决定将什么样的数据存储在集群中的每个NameNode中,例如,可能将所有的用户数据(/user/username)放到一个NameNode中,所有的流数据(/data)放到一个NameNode中,所有的项目(/projects)放到另一个NameNode中等。
为了与Hadoop-1.x提供透明度,ViewFs(比如客户端挂载表)为每个集群创建独立的集群命名空间视图,该视图与hadoop-1.x中的命名空间相似。客户端挂载表就像Unix的挂载表,它们使用旧的命名约定(hadoop-1.x的命名约定)挂载新的命名空间卷。下图展示了一个挂载表挂载了四个命名空间:/user,/data,/projects和/tmp:
ViewFs就像HDFS和本地文件系统一样实现了Hadoop文件系统接口,就其只允许链接到其它文件系统而言,ViewFs是不重要的文件系统。由于实现了Hadoop文件系统接口,ViewFs工作起来是完全透明的,比如在ViewFs中使用shell命令与在HDFS中是一样的。挂载表的挂载点在标准Hadoop配置文件中指定,在每个集群的core-site.xml文件中,默认文件系统设置为集群的挂载表,如下:
<property> <name>fs.defaultFs</name> <value>viewfs://clusterX</value> </property>
上述URI中viewfs:// 之后的认证部分是挂载表的名称,比如clusterX。建议使用集群的名称命名集群中的挂载表。Hadoop系统将在配置文件中查找名为clusterX的挂载表。在为每个集群的默认文件系统设置了ViewFs挂载表后,操作安排所有的网关和服务主机包含所有集群的挂载表。下面看看使用挂载表的典型路径:
distcp viewfs://clusterY/pathSrc viewfs://clusterZ/pathDest
同Hadoop-1.x中的路径名一样,建议使用相对路径名,而且应用程序不应该使用挂载点和hdfs://namenodeContainingUserDirs:port/joe/foo/bar类似的路径引用特定NameNode上的文件,而应使用/user/joe/foo/bar。在hadoop-1.x中不允许跨NameNode或者集群重命名文件或目录,在hadoop-2.x也不允许这样做,并增加了额外的限制,比如在hadoop-1.x中可以执行下面的命令:
rename /user/joe/myStuff /data/foo/bar
在hadoop-2.x中,如果/user和/data在不同的NameNode上,该操作将不会执行成功。
挂载表可以在core-site.xml中定义,但更好的做法是在core-site.xml外部定义一个单独的文件,然后在core-site.xml中引用该文件。挂载表的定义需要在所有集群中进行配置,因为可能需要在其它集群中访问数据,比如distcp命令。当作业提交到集群时读取挂载表,core-site.xml中的引用的挂载表定义文件在作业提交时展开,这意味着如果挂载表改变了,作业需要重新提交。下面通过一个例子展示如何配置挂载表。首先在core-site.xml中增加下面的元素以引用挂载表定义文件mountTable.xml:
<configuration xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href="mountTable.xml" /> </configuration>
假设集群ClusterX是拥有3个命名空间(3个NameNode)的HDFS联盟,3个NameNode分别为nn1-clusterx、nn2-clusterx、nn3-clusterx,其中/home和 /tmp在由nn1-clusterx管理的命名空间中,projects/foo和/bar在另外两个NameNode中,集群的home目录设置为/home,这样可以使用定义在FileSystem或者FileContext中的getHomeDirectory()方法访问home目录。下面是配置文件mountTable.xml中的内容:
<configuration> <property> <name>fs.viewfs.mounttable.ClusterX.homedir</name> <value>/home</value> </property> <property> <name>fs.viewfs.mounttable.ClusterX.link./home</name> <value>hdfs://nn1-clusterx:8020/home</value> </property> <property> <name>fs.viewfs.mounttable.ClusterX.link./tmp</name> <value>hdfs://nn1-clusterx:8020/tmp</value> </property> <property> <name>fs.viewfs.mounttable.ClusterX.link./projects/foo</name> <value>hdfs://nn2-clusterx:8020/projects/foo</value> </property> <property> <name>fs.viewfs.mounttable.ClusterX.link./projects/bar</name> <value>hdfs://nn3-clusterx:8020/projects/bar</value> </property> </configuration>