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租户分配 hdfs federation_命名空间


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

hdfs租户分配 hdfs federation_命名空间_02

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表,典型的路径名是

  1. /foo/bar
  • 这相当于viewfs://clusterX/foo/bar。如果在旧的非联合世界中使用此类路径名,则转换到联合世界是透明的。
  1. viewfs://clusterX/foo/bar
  • 虽然这是一个有效的路径名,但最好使用/foo/bar,因为它允许应用程序及其数据在需要时透明地移动到另一个群集。
  1. viewfs://clusterY/foo/bar
  • 它是用于在另一个集群(如Cluster Y)上引用路径名的URI。特别是,将文件从集群Y复制到集群Z的命令如下所示:
distcp viewfs://clusterY/pathSrc viewfs://clusterZ/pathDest
  1. viewfs://clusterX-webhdfs/foo/bar
  • 它是用于通过WebHDFS文件系统访问文件的URI。
  1. http://namenodeClusterX:http_port/webhdfs/v1/foo/bar and http://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联合具有相同的体系结构。

hdfs租户分配 hdfs federation_HDFS_03

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使用它来获取群集状态。

某些操作在基于路由器的联合中不可用。路由器会抛出异常。用户可能遇到的示例包括以下内容。

  • 在两个不同的名称服务中重命名文件/文件夹。
  • 将文件/文件夹复制到两个不同的名称服务中。
  • 写入正在重新平衡的文件/文件夹。