HDFS Federation 联邦机制
1、HDFS的层级
NameSpace: Directories, Files, Blocks
Block Storage: Block Management, Storage
- 命名空间
- 由目录,文件和块组成。
- 它支持所有与命名空间相关的文件系统操作,例如创建,删除,修改和列出文件和目录。
- 块存储服务,包括两部分:
- 块管理(在Namenode中执行)
- 通过处理注册和定期心跳来提供Datanode集群成员资格。
- 进程阻止报告并维护块的位置。
- 支持块相关操作,如创建,删除,修改和获取块位置。
- 管理副本放置,阻止复制下的块的复制,并删除过度复制的块。
- 存储 - 由Datanodes通过在本地文件系统上存储块并允许读/写访问来提供。
先前的HDFS架构仅允许整个群集使用单个命名空间。在该配置中,单个Namenode管理命名空间。HDFS Federation通过向HDFS添加对多个Namenodes 名称空间的支持来解决此限制。
2、HDFS 单namenode架构局限性
NameSpace(命名空间的限制)
由于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的内存使用性价比比较低
3、HDFS Federation机制的引入
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的命令;
4、使用时的问题
1、访问HDFS的路径及NameSpace视图可以通过ViewFileSystem和viewfs://URI进行配置和管理。
2、路径变更后,所有使用Schema路径均要变更,如Hive meta 、ETL脚本、MR/Spark中所有的HDFS路径
3、并未完全解决单点故障,每一个NameNode还是相对独立,需要对每一个NameNode实行HA
5、配置相关
配置文件以两个NameNode为例:
<configuration>
<property>
<name>dfs.nameservices</name>
<value>ns1,ns2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.ns1</name>
<value>nn-host1:rpc-port</value>
</property>
<property>
<name>dfs.namenode.http-address.ns1</name>
<value>nn-host1:http-port</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address.ns1</name>
<value>snn-host1:http-port</value>
</property>
<property>
<name>dfs.namenode.rpc-address.ns2</name>
<value>nn-host2:rpc-port</value>
</property>
<property>
<name>dfs.namenode.http-address.ns2</name>
<value>nn-host2:http-port</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address.ns2</name>
<value>snn-host2:http-port</value>
</property>
.... Other common configuration ...
</configuration>
格式化集群NN
步骤1:使用以下命令格式化Namenode:
[hdfs] $ $ HADOOP_PREFIX/bin/hdfs namenode -format [-clusterId <cluster_id>]
选择一个唯一的cluster_id,它不会与环境中的其他群集冲突。如果未提供cluster_id,则会自动生成唯一的cluster_id。
步骤2:使用以下命令格式化其他Namenodes:
[hdfs] $ $ HADOOP_PREFIX/bin/hdfs namenode -format -clusterId <cluster_id>
请注意,步骤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 <datanode_host_name>:<datanode_rpc_port>
HDFS Federation和ViewFS
1、理解
假设有多个集群。每个群集都有一个或多个名称节点。每个namenode都有自己的命名空间。namenode属于一个且只有一个集群。同一群集中的名称节点共享该群集的物理存储。跨群集的命名空间与以前一样是独立的。
操作根据存储需求决定群集中每个名称节点上存储的内容。例如,他们可以将所有用户数据(/user /<username>
)放在一个namenode中,将所有feed-data(/data
)放在另一个namenode中,将所有项目(/projects
)放在另一个namenode中,等等。
2、使用ViewFS为每个群集做全局命名空间
为了提供旧世界的透明性,ViewFs文件系统(即客户端安装表)用于为每个集群创建一个独立的集群命名空间视图,该视图类似于旧世界中的命名空间。客户端安装表,如Unix安装表,它们使用旧的命名约定安装新的命名空间卷。下图显示了一个挂载表,用于挂载四个命名空间卷/ user
,/ data
,/ projects
和/ tmp
:
ViewFs实现Hadoop文件系统接口,就像HDFS和本地文件系统一样。从某种意义上说,它只是一个简单的文件系统,它只允许链接到其他文件系统。由于ViewF实现了Hadoop文件系统接口,因此它可以透明地使用Hadoop工具。例如,与HDFS和本地文件系统一样,所有shell命令都与ViewF一起使用。
在每个群集的配置中,默认文件系统设置为该群集的装载表,如下所示(将其与Single Namenode Clusters中的配置进行比较)。
<property>
<name>fs.defaultFS</name>
<value>viewfs://clusterX</value>
</property>
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
。
<configuration>
<property>
<name>fs.viewfs.mounttable.ClusterX.link./data</name>
<value>hdfs://nn1-clusterx.example.com:8020/data</value>
</property>
<property>
<name>fs.viewfs.mounttable.ClusterX.link./project</name>
<value>hdfs://nn2-clusterx.example.com:8020/project</value>
</property>
<property>
<name>fs.viewfs.mounttable.ClusterX.link./user</name>
<value>hdfs://nn3-clusterx.example.com:8020/user</value>
</property>
<property>
<name>fs.viewfs.mounttable.ClusterX.link./tmp</name>
<value>hdfs://nn4-clusterx.example.com:8020/tmp</value>
</property>
<property>
<name>fs.viewfs.mounttable.ClusterX.linkFallback</name>
<value>hdfs://nn5-clusterx.example.com:8020/home</value>
</property>
</configuration>
或者,我们可以通过linkMergeSlash
将mount表的根与另一个文件系统的根合并。在下面的安装表配置中,ClusterY的根与hdfs://nn1-clustery.example.com:8020
上的根文件系统合并。
<configuration>
<property>
<name>fs.viewfs.mounttable.ClusterY.linkMergeSlash</name>
<value>hdfs://nn1-clustery.example.com:8020/</value>
</property>
</configuration>
3、路径名使用模式
因此,在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
- 它是用于通过WebHDFS文件系统访问文件的URI。
http://namenodeClusterX:http_port/webhdfs/v1/foo/bar
andhttp://proxyClusterX:http_port/foo/bar
- 这些是分别用于通过WebHDFS REST API和HDFS代理访问文件的HTTP URL 。请注意,它们与以前相同。
4、路径名使用最佳实践
当一个在群集中时,建议使用上面类型(1)的路径名而不是像(2)那样的完全限定URI。此外,应用程序不应使用挂载点的知识,并使用类似hdfs://namenodeContainingUserDirs:port/joe/foo/bar
的路径来引用特定namenode中的文件。应该使用/user/joe/foo/bar
代替。
5、重命名命名空间的路径名
回想一下,不能在旧世界中的名称节点或集群中重命名文件或目录。新世界也是如此,但还有一个额外的转折点。例如,在旧世界中,人们可以执行下面的推荐。
rename /user/joe/myStuff /data/foo/bar
如果/user
和/data
实际存储在集群中的不同名称节点上,则这在新世界中不起作用。
HDFS Router Based Federation
1、介绍
HDFS Router-Based Federation 添加了一个 RPC路由层,提供了多个 HDFS 命名空间的联合视图。与现有 ViewFs 和 HDFS Federation 功能类似,不同之处在于挂载表(mount table)由服务器端(server-side)的路由层维护,而不是客户端。这简化了现有 HDFS客户端 对 federated cluster 的访问。
2、建筑
此分区联合的自然扩展是添加一个负责联合命名空间的软件层。这个额外的层允许用户透明地访问任何子集群,让子集独立管理他们自己的块池,并支持稍后跨子集重新平衡数据(请参阅HDFS-13123中的更多信息)。RBF中的子群集不需要是独立的HDFS群集,也可以是普通联合群集(具有多个块池)或具有联合和独立群集的混合群集。为了实现这些目标,联合层将块访问指向正确的子集群,维护命名空间的状态,并提供数据重新平衡的机制。该层必须具有可扩展性,高可用性和容错性。
该联合层包括多个组件。该路由器组件具有相同的接口作为NameNode的,并且客户端请求到正确的子群集转发的基础上,based on ground-truth information from a State Store.基于从State Store获取的底层实况信息。该State Store结合了远程安装台(在风味ViewFs,但客户端之间共享)和利用(加载/容量)有关子群集信息。此方法与YARN联合具有相同的体系结构。
3、示例流程
最简单的配置在每个NameNode计算机上部署路由器。路由器监视本地NameNode并将状态检测到状态存储。当常规DFS客户端联系任何路由器以访问联合文件系统中的文件时,路由器会检查状态存储中的挂载表(即本地缓存)以找出包含该文件的子集群。然后,它检查State Store中的Membership表(即本地缓存),以查找负责子集群的NameNode。在识别出正确的NameNode之后,路由器代理请求。客户端直接访问Datanodes。
4、路由器
系统中可以有多个具有软状态的路由器。每个路由器都有两个角色:
- 联合接口:向客户端公开单个全局NameNode接口,并将请求转发到正确子集群中的活动NameNode
- NameNode心跳:维护State Store中NameNode的信息
联邦接口
路由器接收客户端请求,检查State Store中是否有正确的子集群,并将请求转发到该子集群的活动NameNode。然后,NameNode的回复以相反的方向流动。路由器是无状态的,可以在负载均衡器后面。对于运行状况检查,可以使用/ isActive端点作为运行状况探测(例如http://ROUTER_HOSTNAME:ROUTER_PORT/isActive)。为了提高性能,路由器还会缓存远程装载表条目和子群集的状态。为确保更改已传播到所有路由器,每个路由器将其状态检测到状态存储。
路由器和状态存储之间的通信被缓存(具有定时到期的新鲜度)。这提高了系统的性能。
NameNode心跳
对于此角色,路由器会定期检查NameNode的状态(通常位于同一服务器上),并将其高可用性(HA)状态和负载/空间状态报告给State Store。请注意,这是一个可选角色,因为路由器可以独立于任何子集群。对于使用NameNode HA的性能,路由器使用State Store中的高可用性状态信息将请求转发到最可能处于活动状态的NameNode。请注意,此服务可以嵌入到NameNode本身中以简化操作。
可用性和容错性
路由器在多个级别上运行故障。
- **联合接口HA:**路由器是无状态的,元数据操作在NameNode处是原子的。如果路由器不可用,任何路由器都可以接管它。客户端将联合中的所有路由器配置为DFS HA客户端(例如,ConfiguredFailoverProvider或RequestHedgingProxyProvider)作为端点。
- **不可用的State Store:**如果路由器无法联系State Store,它将进入安全模式状态,不允许它提供请求。客户端将以安全模式处理路由器,因为它是备用NameNode并尝试其他路由器。有一种手动方式来管理路由器的安全模式。
可以使用以下命令管理安全模式状态:
[hdfs]$ $HADOOP_HOME/bin/hdfs dfsrouteradmin -safemode enter | leave | get
- **NameNode心跳HA:**为了实现高可用性和灵活性,多个路由器可以监视相同的NameNode,并将信息心跳到State Store。如果路由器出现故障,这会增加客户端对陈旧信息的弹性。每个路由器通过仲裁解决状态存储中的冲突NameNode信息。
- **不可用的NameNodes:**如果路由器无法联系活动的NameNode,那么它将尝试子集群中的其他NameNode。它将首先尝试报告为待机状态,然后是不可用状态。如果路由器无法访问任何NameNode,则会抛出异常。
- **Expired NameNodes:**如果状态存储中没有记录NameNode心跳的心跳间隔的多倍,监视路由器将记录NameNode已过期且没有路由器将尝试访问它。如果随后为NameNode记录更新的心跳,则监视路由器将从过期状态恢复NameNode。
接口
为了与用户和管理员进行交互,路由器公开了多个接口。
- **RPC:**路由器RPC实现客户端用于与HDFS交互的最常见接口。目前的实现已经使用普通MapReduce,Spark和Hive(在Tez,Spark和MapReduce上)编写的分析工作负载进行了测试。快照,加密和分层存储等高级功能留待未来版本使用。所有未实现的函数都会抛出异常。
- **管理员:**管理员可以从群集中查询信息,并通过RPC在装载表中添加/删除条目。此接口也通过命令行公开,以获取和修改联合的信息。
- **Web UI:**路由器公开Web UI,可视化联合的状态,模仿当前的NameNode UI。它显示有关装入表的信息,有关每个子群集的成员身份信息以及路由器的状态。
- **WebHDFS:**除了RPC之外,路由器还提供HDFS REST接口(WebHDFS)。
- **JMX:**它通过模仿NameNode的JMX公开指标。Web UI使用它来获取群集状态。
某些操作在基于路由器的联合中不可用。路由器会抛出异常。用户可能遇到的示例包括以下内容。
- 在两个不同的名称服务中重命名文件/文件夹。
- 将文件/文件夹复制到两个不同的名称服务中。
- 写入正在重新平衡的文件/文件夹。
配额管理
公开,以获取和修改联合的信息。
- **Web UI:**路由器公开Web UI,可视化联合的状态,模仿当前的NameNode UI。它显示有关装入表的信息,有关每个子群集的成员身份信息以及路由器的状态。
- **WebHDFS:**除了RPC之外,路由器还提供HDFS REST接口(WebHDFS)。
- **JMX:**它通过模仿NameNode的JMX公开指标。Web UI使用它来获取群集状态。
某些操作在基于路由器的联合中不可用。路由器会抛出异常。用户可能遇到的示例包括以下内容。
- 在两个不同的名称服务中重命名文件/文件夹。
- 将文件/文件夹复制到两个不同的名称服务中。
- 写入正在重新平衡的文件/文件夹。