NameSpace: Directories, Files, Blocks
Block Storage: Block Management, Storage
命名空间
- 由目录,文件和块组成。
- 它支持所有与命名空间相关的文件系统操作,例如创建,删除,修改和列出文件和目录。
块存储服务,包括两部分:
- 块管理(在Namenode中执行)
- 通过处理注册和定期心跳来提供Datanode集群成员资格。
- 进程阻止报告并维护块的位置。
- 支持块相关操作,如创建,删除,修改和获取块位置。
- 管理副本放置,阻止复制下的块的复制,并删除过度复制的块。
- 存储 - 由Datanodes通过在本地文件系统上存储块并允许读/写访问来提供。
先前的HDFS架构仅允许整个群集使用单个命名空间。在该配置中,单个Namenode管理命名空间。HDFS Federation通过向HDFS添加对多个Namenodes 名称空间的支持来解决此限制。
由于Namenode在内存中存储所有的元数据(metadata)。NN在管理大规模的命名空间时,单个Namenode所能存储的对象(文件+块)数目受到Namenode所在JVM的堆【内存大小的限制】。
随着数据的飞速增长,存储的需求也随之增长。50G的heap能够存储20亿个对象—>4000个datanode—>12PB的存储(假设文件平均大小为40MB)。单个datanode从4T增长到36T,集群的尺寸增长到8000个datanode。存储的需求从12PB增长到大于100PB。
由于是单个Namenode的HDFS架构,因此整个HDFS文件系统的吞吐量受限于单个NameNode的吞吐量。这将成为下一代MapReduce的瓶颈。
由于仅有一个Namenode,无法隔离各个程序,因此HDFS上的一个实验程序很可能影响整个HDFS上运行的程序。 NN在内部用一把全局锁撸遍所有的元数据操作来保证数据的一致性
在只有一个Namenode的HDFS中,此Namenode的宕机无疑会导致整个集群的不可用。(低可用性)
Namespace和Block Management(管理)的紧密耦合
Hadoop 1.x在Namenode中的Namespace和Block Management组合的紧密耦合关系会导致如果想要实现另外一套。Namenode方案比较困难,而且也限制了其他想要直接使用块存储的应用。
为什么纵向扩展目前的NameNode不可行?比如将NameNode的Heap堆空间扩大到512GB。
1.启动时间太长。(Hadoop 1.x具有50GB Heap Namenode的HDFS启动一次大概需要30分钟到2小时)
2.Namenode在Full GC时,如果发生错误将会导致整个集群宕机。
3.对大JVM Heap进行调试比较困难。优化Namenode的内存使用性价比比较低
Hadoop-2.X版本引入
HDFS Federation对NameNode做了横向的拓展,其中每一个namenode管理文件系统命名空间中的一部分。
每一个NN都要维护一个命名空间卷(Name Space Volume),由命名空间的元数据和一个数据块池组成。
数据块池(Block Pool)包含了该命名空间下文件的所有数据块。
1、多个NameNode是联合的;
2、NameNode之间互相独立,不需要协调;
3、DataNode之间用作所有NameNode的快的公共存储;
4、DataNode需要对所有NameNode进行注册;
5、DataNode定期发送心跳和Block报告给所有的NN;
6、DataNode需要处理来自所有NN的命令;
1、访问HDFS的路径及NameSpace视图可以通过ViewFileSystem和viewfs://URI进行配置和管理。
2、路径变更后,所有使用Schema路径均要变更,如Hive meta 、ETL脚本、MR/Spark中所有的HDFS路径
3、并未完全解决单点故障,每一个NameNode还是相对独立,需要对每一个NameNode实行HA
配置文件以两个NameNode为例:
<configuration>
<property>
<name>dfs.nameservicesname>
<value>ns1,ns2value>
property>
<property>
<name>dfs.namenode.rpc-address.ns1name>
<value>nn-host1:rpc-portvalue>
property>
<property>
<name>dfs.namenode.http-address.ns1name>
<value>nn-host1:http-portvalue>
property>
<property>
<name>dfs.namenode.secondary.http-address.ns1name>
<value>snn-host1:http-portvalue>
property>
<property>
<name>dfs.namenode.rpc-address.ns2name>
<value>nn-host2:rpc-portvalue>
property>
<property>
<name>dfs.namenode.http-address.ns2name>
<value>nn-host2:http-portvalue>
property>
<property>
<name>dfs.namenode.secondary.http-address.ns2name>
<value>snn-host2:http-portvalue>
property>
.... Other common configuration ...
configuration>
格式化集群NN
步骤1:使用以下命令格式化Namenode:
[hdfs] $ $ HADOOP_PREFIX/bin/hdfs namenode -format [-clusterId ]
选择一个唯一的cluster_id,它不会与环境中的其他群集冲突。如果未提供cluster_id,则会自动生成唯一的cluster_id。
步骤2:使用以下命令格式化其他Namenodes:
[hdfs] $ $ HADOOP_PREFIX/bin/hdfs namenode -format -clusterId
请注意,步骤2中的cluster_id必须与步骤1中的cluster_id的cluster_id相同。如果它们不同,则其他Namenodes将不是联合群集的一部分。
将新Namenode添加到现有HDFS集群
执行以下步骤:
将dfs.nameservices
添加到配置中。
使用NameServiceID后缀更新配置。版本0.20后配置密钥名称已更改。必须使用新的配置参数名称才能使用联合。
将新的Namenode相关配置添加到配置文件中。
将配置文件传播到集群中的所有节点。
启动新的Namenode和Secondary / Backup。
刷新Datanodes以通过对集群中的所有Datanode运行以下命令来拾取新添加的Namenode:
[hdfs] $ $ HADOOP_PREFIX/bin/hdfs dfsadmin -refreshNamenodes :
假设有多个集群。每个群集都有一个或多个名称节点。每个namenode都有自己的命名空间。namenode属于一个且只有一个集群。同一群集中的名称节点共享该群集的物理存储。跨群集的命名空间与以前一样是独立的。
操作根据存储需求决定群集中每个名称节点上存储的内容。例如,他们可以将所有用户数据(/user /
)放在一个namenode中,将所有feed-data(/data
)放在另一个namenode中,将所有项目(/projects
)放在另一个namenode中,等等。
为了提供旧世界的透明性,ViewFs文件系统(即客户端安装表)用于为每个集群创建一个独立的集群命名空间视图,该视图类似于旧世界中的命名空间。客户端安装表,如Unix安装表,它们使用旧的命名约定安装新的命名空间卷。下图显示了一个挂载表,用于挂载四个命名空间卷/ user
,/ data
,/ projects
和/ tmp
:
ViewFs实现Hadoop文件系统接口,就像HDFS和本地文件系统一样。从某种意义上说,它只是一个简单的文件系统,它只允许链接到其他文件系统。由于ViewF实现了Hadoop文件系统接口,因此它可以透明地使用Hadoop工具。例如,与HDFS和本地文件系统一样,所有shell命令都与ViewF一起使用。
在每个群集的配置中,默认文件系统设置为该群集的装载表,如下所示(将其与Single Namenode Clusters中的配置进行比较)。
fs.defaultFS
viewfs://clusterX
URI中viewfs://
方案后面的权限
是挂载表名称。建议群集的挂载表应按群集名称命名。然后Hadoop系统将在Hadoop配置文件中查找名为“clusterX”的挂载表。操作安排所有网关和服务机器包含所有群集的装载表,以便对于每个群集,将默认文件系统设置为该群集的ViewFs装载表,如上所述。
挂载表的挂载点在标准Hadoop配置文件中指定。viewfs的
所有mount表配置条目都以fs.viewfs.mounttable
为前缀。
。使用链接
标记指定链接其他文件系统的挂载点。建议使挂载点名称与链接文件系统目标位置中的相同。对于未在mount表中配置的所有命名空间,我们可以通过linkFallback
将它们回退到
默认文件系统。
在下面的挂载表配置中,命名空间/数据
链接到文件系统hdfs://nn1-clusterx.example.com:8020/data
,/project
链接到文件系统hdfs://nn2-clusterx.example.com:8020/项目
。未在mount表中配置的所有命名空间(如/logs)
都链接到文件系统hdfs://nn5-clusterx.example.com:8020/home
。
fs.viewfs.mounttable.ClusterX.link./data
hdfs://nn1-clusterx.example.com:8020/data
fs.viewfs.mounttable.ClusterX.link./project
hdfs://nn2-clusterx.example.com:8020/project
fs.viewfs.mounttable.ClusterX.link./user
hdfs://nn3-clusterx.example.com:8020/user
fs.viewfs.mounttable.ClusterX.link./tmp
hdfs://nn4-clusterx.example.com:8020/tmp
fs.viewfs.mounttable.ClusterX.linkFallback
hdfs://nn5-clusterx.example.com:8020/home
或者,我们可以通过linkMergeSlash
将mount表的根与另一个文件系统的根合并。在下面的安装表配置中,ClusterY的根与hdfs://nn1-clustery.example.com:8020
上的根文件系统合并。
fs.viewfs.mounttable.ClusterY.linkMergeSlash
hdfs://nn1-clustery.example.com:8020/
因此,在Cluster X上,core-site.xml
设置为使默认fs使用该集群的mount表,典型的路径名是
/foo/bar
viewfs://clusterX/foo/bar
。如果在旧的非联合世界中使用此类路径名,则转换到联合世界是透明的。viewfs://clusterX/foo/bar
/foo/bar,
因为它允许应用程序及其数据在需要时透明地移动到另一个群集。viewfs://clusterY/foo/bar
它是用于在另一个集群(如Cluster Y)上引用路径名的URI。特别是,将文件从集群Y复制到集群Z的命令如下所示:
distcp viewfs://clusterY/pathSrc viewfs://clusterZ/pathDest
viewfs://clusterX-webhdfs/foo/bar
http://namenodeClusterX:http_port/webhdfs/v1/foo/bar
and http://proxyClusterX:http_port/foo/bar
当一个在群集中时,建议使用上面类型(1)的路径名而不是像(2)那样的完全限定URI。此外,应用程序不应使用挂载点的知识,并使用类似hdfs://namenodeContainingUserDirs:port/joe/foo/bar
的路径来引用特定namenode中的文件。应该使用/user/joe/foo/bar
代替。
回想一下,不能在旧世界中的名称节点或集群中重命名文件或目录。新世界也是如此,但还有一个额外的转折点。例如,在旧世界中,人们可以执行下面的推荐。
rename /user/joe/myStuff /data/foo/bar
如果/user
和/data
实际存储在集群中的不同名称节点上,则这在新世界中不起作用。
HDFS Router-Based Federation 添加了一个 RPC路由层,提供了多个 HDFS 命名空间的联合视图。与现有 ViewFs 和 HDFS Federation 功能类似,不同之处在于挂载表(mount table)由服务器端(server-side)的路由层维护,而不是客户端。这简化了现有 HDFS客户端 对 federated cluster 的访问。
此分区联合的自然扩展是添加一个负责联合命名空间的软件层。这个额外的层允许用户透明地访问任何子集群,让子集独立管理他们自己的块池,并支持稍后跨子集重新平衡数据(请参阅HDFS-13123中的更多信息)。RBF中的子群集不需要是独立的HDFS群集,也可以是普通联合群集(具有多个块池)或具有联合和独立群集的混合群集。为了实现这些目标,联合层将块访问指向正确的子集群,维护命名空间的状态,并提供数据重新平衡的机制。该层必须具有可扩展性,高可用性和容错性。
该联合层包括多个组件。该路由器组件具有相同的接口作为NameNode的,并且客户端请求到正确的子群集转发的基础上,based on ground-truth information from a State Store.基于从State Store获取的底层实况信息。该State Store结合了远程安装台(在风味ViewFs,但客户端之间共享)和利用(加载/容量)有关子群集信息。此方法与YARN联合具有相同的体系结构。
最简单的配置在每个NameNode计算机上部署路由器。路由器监视本地NameNode并将状态检测到状态存储。当常规DFS客户端联系任何路由器以访问联合文件系统中的文件时,路由器会检查状态存储中的挂载表(即本地缓存)以找出包含该文件的子集群。然后,它检查State Store中的Membership表(即本地缓存),以查找负责子集群的NameNode。在识别出正确的NameNode之后,路由器代理请求。客户端直接访问Datanodes。
系统中可以有多个具有软状态的路由器。每个路由器都有两个角色:
路由器接收客户端请求,检查State Store中是否有正确的子集群,并将请求转发到该子集群的活动NameNode。然后,NameNode的回复以相反的方向流动。路由器是无状态的,可以在负载均衡器后面。对于运行状况检查,可以使用/ isActive端点作为运行状况探测(例如http://ROUTER_HOSTNAME:ROUTER_PORT/isActive)。为了提高性能,路由器还会缓存远程装载表条目和子群集的状态。为确保更改已传播到所有路由器,每个路由器将其状态检测到状态存储。
路由器和状态存储之间的通信被缓存(具有定时到期的新鲜度)。这提高了系统的性能。
对于此角色,路由器会定期检查NameNode的状态(通常位于同一服务器上),并将其高可用性(HA)状态和负载/空间状态报告给State Store。请注意,这是一个可选角色,因为路由器可以独立于任何子集群。对于使用NameNode HA的性能,路由器使用State Store中的高可用性状态信息将请求转发到最可能处于活动状态的NameNode。请注意,此服务可以嵌入到NameNode本身中以简化操作。
路由器在多个级别上运行故障。
可以使用以下命令管理安全模式状态:
[hdfs]$ $HADOOP_HOME/bin/hdfs dfsrouteradmin -safemode enter | leave | get
为了与用户和管理员进行交互,路由器公开了多个接口。
某些操作在基于路由器的联合中不可用。路由器会抛出异常。用户可能遇到的示例包括以下内容。
公开,以获取和修改联合的信息。
某些操作在基于路由器的联合中不可用。路由器会抛出异常。用户可能遇到的示例包括以下内容。
联合在mount表级别支持和控制全局配额。出于性能原因,路由器会缓存配额使用情况并定期更新。在RouterRPCSever中调用的每个WRITE RPC调用期间,这些配额使用值将用于配额验证。有关配额详细信息,请参阅HDFS配额指南。