前言

当数据集超过一个单独的物理计算机的存储能力时,便有必要将它分部到多个独立的计算机。管理跨计算机网络存储的文件系统成为分布式文件系统。因为它们是基于网络的,所有网络编程的复杂性都会随之而来,所以分布式文件系统比普通磁盘文件系统更复杂。使这个文件系统能容忍节点故障而不损失数据就是一个极大的挑战。

HDFS的设计

HDFS是为以流式出局访问模式存储超大文件而设计的文件系统,在商用硬件的集群上运行。让我们看看它的优势:
超大文件
“超大文件”在这里指几百MB,几百GB甚至几百TB大小的文件。目前已经有Hadoop集群存储PB级的数据了。
流式数据
HDFS建立在这样一个思想上:一次写入、多次读取模式是最高效的。一个数据集通常由数据源生成或复制,接着在此基础上进行各种各样的分析。每个分析至少都会涉及数据集中的大部分数据(甚至全部)。
商用硬件
Hadoop不需要运行在昂贵并且高可靠的硬件上。它被设计运行在商用硬件(在各种零售店都能买到的普通硬件)的集群上,因此至少对于大的集群来说,节点故障的几率还是较高的。HDFS在面对这种故障时,被设计为能够继续运行而让用户察觉不到明显的中断。

HDFS 1.0架构:

HDFS采用的是Master/Slave架构一个 HDFS 集群包含一个单独的 NameNode 和多个 DataNode 节点。

HDFS 1.0 的问题

进入了 PB 级的大数据时代,HDFS 1.0的设计缺陷已经无法满足生产的需求,最致命的问题有以下两点:

  • NameNode 的单点问题,如果 NameNode 挂掉了,数据读写都会受到影响,HDFS 整体将变得不可用,这在生产环境中是不可接受的;
  • 水平扩展问题,随着集群规模的扩大,1.0 时集群规模达到3000时,会导致整个集群管理的文件数目达到上限(因为 NameNode 要管理整个集群 block 元信息、数据目录信息等)。

为了解决上面的两个问题,Hadoop2.0 提供一套统一的解决方案:

  • HA(High Availability 高可用方案):这个是为了解决 NameNode 单点问题;
  • NameNode Federation:是用来解决 HDFS 集群的线性扩展能力。

HDFS 2.0 的 HA 实现

这里先看下 HDFS 高可用解决方案的架构设计,如下图

图片说明

这里与前面 1.0 的架构已经有很大变化,简单介绍一下的组件:

  1. Active NameNode 和 Standby NameNode:两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务;
  2. ZKFailoverController(主备切换控制器,FC):ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换(当然 NameNode 目前也支持不依赖于Zookeeper 的手动主备切换);
  3. Zookeeper 集群:为主备切换控制器提供主备选举支持;
  4. 共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。主 NameNode 和备NameNode 通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元数据完全同步之后才能继续对外提供服务。
  5. DataNode 节点:因为主 NameNode 和备 NameNode 需要共享 HDFS 的数据块和 DataNode 之间的映射关系,为了使故障切换能够快速进行,DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。

HDFS 2.0 Federation 实现

在 1.0 中,HDFS 的架构设计有以下缺点:

namespace 扩展性差:在单一的 NN 情况下,因为所有 namespace 数据都需要加载到内存,所以物理机内存的大小限制了整个 HDFS 能够容纳文件的最大个数(namespace 指的是 HDFS 中树形目录和文件结构以及文件对应的 block 信息);
性能可扩展性差:由于所有请求都需要经过 NN,单一 NN 导致所有请求都由一台机器进行处理,很容易达到单台机器的吞吐;
隔离性差:多租户的情况下,单一 NN 的架构无法在租户间进行隔离,会造成不可避免的相互影响。
而 Federation 的设计就是为了解决这些问题,采用 Federation 的最主要原因是设计实现简单,而且还能解决问题。

Federation 架构

Federation 的架构设计如下图所示(图片来自 HDFS Federation):
图片说明

HDFS Federation 架构实现

Federation 的核心设计思想
Federation 的核心思想是将一个大的 namespace 划分多个子 namespace,并且每个 namespace 分别由单独的 NameNode 负责,这些 NameNode 之间互相独立,不会影响,不需要做任何协调工作(其实跟拆集群有一些相似),集群的所有 DataNode 会被多个 NameNode 共享。

其中,每个子 namespace 和 DataNode 之间会由数据块管理层作为中介建立映射关系,数据块管理层由若干数据块池(Pool)构成,每个数据块只会唯一属于某个固定的数据块池,而一个子 namespace 可以对应多个数据块池。每个 DataNode 需要向集群中所有的 NameNode 注册,且周期性地向所有 NameNode 发送心跳和块报告,并执行来自所有 NameNode 的命令。

  1. 一个 block pool 由属于同一个 namespace 的数据块组成,每个 DataNode 可能会存储集群中所有 block pool 的数据块;
  2. 每个 block pool 内部自治,也就是说各自管理各自的 block,不会与其他 block pool 交流,如果一个 NameNode 挂掉了,不会影响其他 NameNode;
  3. 某个 NameNode 上的 namespace 和它对应的 block pool 一起被称为 namespace volume,它是管理的基本单位。当一个 NameNode/namespace 被删除后,其所有 DataNode 上对应的 block pool 也会被删除,当集群升级时,每个 namespace volume 可以作为一个基本单元进行升级。
    参考链接:
    https://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop-name-node/
    http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/Federation.html