HDFS架构

引言

HDFS 是一个基于硬件的分散式档案系统分散式档案系统。它与现有的分布式文件系统有许多相似之处。然而,与其他分布式文件系统的区别是显著的。HDFS 具有很高的容错能力,可以部署在低成本的硬件上。HDFS 提供对应用程序数据的高吞吐量访问,适用于拥有大型数据集的应用程序。HDFS 放松了一些 POSIX 要求,允许对文件系统数据的流式访问。HDFS 最初是作为 Apache Nutch 网络搜索引擎项目的基础设施而构建的。HDFS 是 Apache Hadoop Core 项目的一部分。这个项目的网址是 https://hadoop.apache.org/。

假设和目标

硬件故障

硬件故障是家常便饭,而不是例外。一个 HDFS 实例可能由数百或数千台服务器机器组成,每台机器都存储文件系统的部分数据。事实上,有大量的组件,而且每个组件都有不小的失败概率,这意味着 HDFS 的某些组件总是不能正常工作。因此,故障检测和快速、自动恢复是 HDFS 的核心体系结构目标。

流式数据访问

在 HDFS 上运行的应用程序需要对其数据集进行流访问。它们不是通用应用程序,通常在通用文件系统上运行。HDFS 更多是为批处理而设计的,而不是用户的交互式使用。重点是高吞吐量的数据访问,而不是低延迟的数据访问。POSIX 强加了许多针对 HDFS 的应用程序不需要的硬性要求。为了提高数据吞吐率,交易了一些关键领域中的 POSIX 语义。

大型数据集

在 HDFS 上运行的应用程序有大量的数据集。HDFS 中的典型文件大小为 g 到 t 字节。因此,HDFS 被调整为支持大文件。它应该能够提供高聚合数据带宽,并且能够扩展到单个集群中的数百个节点。它应该在一个实例中支持数千万个文件。

简单相干模型

HDFS 应用程序需要文件的一次写多读访问模型。创建、写入和关闭文件后,除了追加和截断之外,不需要更改文件。支持将内容追加到文件末尾,但不能在任意点更新。这个假设简化了数据一致性问题,并支持高吞吐量数据访问。MapReduce 应用程序或 web 爬虫应用程序完全符合这个模型。

“移动计算比移动数据便宜”

应用程序请求的计算如果在它所操作的数据附近执行,则效率会高得多。当数据集的规模很大时尤其如此。这最大限度地减少了拥塞控制,并提高了系统的总吞吐量。这里的假设是,将计算迁移到更接近数据所在的位置,而不是将数据移动到应用程序运行的位置,这样做通常更好。HDFS 为应用程序提供接口,使它们自己更接近数据所在的位置。

跨异构硬件和软件平台的可移植性

HDFS 被设计成可以很容易地从一个平台移植到另一个平台。这促进了 HDFS 作为大量应用程序的首选平台的广泛采用。

和 DataNodes

HDFS 有一个主/从架构。HDFS 集群由一个 NameNode 组成,一个主服务器管理文件系统名称空间并规范客户端对文件的访问。此外,还有许多 DataNodes (通常是集群中的每个节点一个) ,它们管理连接到它们运行的节点的存储。HDFS 公开文件系统名称空间,并允许将用户数据存储在文件中。在内部,文件被分割成一个或多个块,这些块存储在一组 DataNodes 中。NameNode 执行文件系统命名空间操作,如打开、关闭和重命名文件和目录。它还确定块到 DataNodes 的映射。DataNodes 负责服务来自文件系统客户端的读写请求。Datanode 还根据 NameNode 的指令执行块创建、删除和复制。

HDFS Architecture

NameNode 和 DataNode 是设计用于在普通机器上运行的软件。这些机器通常运行 GNU/Linux 操作系统(OS)。HDFS 使用 Java 语言构建; 任何支持 Java 的机器都可以运行 NameNode 或 DataNode 软件。使用高度可移植的 Java 语言意味着 HDFS 可以部署在很多机器上。一个典型的部署有一个专用的机器,它只运行 NameNode 软件。集群中的每个其他机器都运行 DataNode 软件的一个实例。该体系结构并不排除在同一台机器上运行多个 datanode,但在实际部署中很少出现这种情况。

集群中单个 NameNode 的存在极大地简化了系统的体系结构。NameNode 是所有 HDFS 元数据的仲裁者和存储库。系统的设计使得用户数据永远不会在 NameNode 中流动。

文件系统名称空间

HDFS 支持传统的分层文件组织。用户或应用程序可以创建目录并将文件存储在这些目录中。文件系统名称空间层次结构类似于大多数其他现有文件系统; 可以创建和删除文件,将文件从一个目录移动到另一个目录,或者重命名文件。HDFS 支持用户配额和访问权限。HDFS 不支持硬链接或软链接。然而,HDFS 架构并不排除实现这些特性。

NameNode 维护文件系统名称空间。对文件系统命名空间或其属性的任何更改都由 NameNode 记录。应用程序可以指定应由 HDFS 维护的文件副本的数量。文件的副本数称为该文件的复制因子。此信息由 NameNode 存储。

数据复制

HDFS 被设计用于在大型集群中跨计算机可靠地存储非常大的文件。它将每个文件存储为一个块序列。为了容错,复制文件的块。每个文件的块大小和复制因子都是可配置的。

文件中除了最后一个块之外的所有块都是相同的大小,而用户可以启动一个新块,而不需要将最后一个块填充到配置的块大小,因为可变长度块的支持添加到了 append 和 hsync 中。

应用程序可以指定文件的副本数。可以在创建文件时指定复制因子,以后可以更改。HDFS 中的文件只写一次(除了追加和截断) ,并且在任何时候都严格只有一个写入器。

NameNode 做出所有关于块复制的决定。它定期从集群中的每个 DataNodes 接收 Heartbeat 和 Blockreport。接收 Heartbeat 意味着 DataNode 正常运行。Blockreport 包含 DataNode 上所有块的列表。

HDFS DataNodes

复制放置: 第一个婴儿步骤

副本的放置对 HDFS 的可靠性和性能至关重要。优化副本放置将 HDFS 区别于大多数其他分布式文件系统。这是一个需要大量调优和经验的特性。机架感知的副本放置策略的目的是提高数据的可靠性、可用性和网络带宽利用率。当前的副本放置策略实现是这方面的第一个努力。实现此策略的短期目标是在生产系统上验证它,更多地了解它的行为,并为测试和研究更复杂的策略奠定基础。

大型 HDFS 实例运行在一组计算机上,这些计算机通常分布在许多机架上。不同机架中的两个节点之间的通信必须经过交换机。在大多数情况下,同一机架上机器之间的网络带宽大于不同机架上机器之间的网络带宽。

NameNode 通过 Hadoop Rack Awareness 中描述的过程确定每个 DataNode 所属的 Rack id。一个简单但非最优的策略是将副本放在独特的机架上。这可以防止当整个机架出现故障时丢失数据,并允许在读取数据时使用多个机架的带宽。这个策略将副本均匀地分布在集群中,这样可以很容易地平衡组件故障时的负载。但是,此策略增加了写操作的成本,因为写操作需要将块传输到多个机架。

对于常见的情况,当复制因子为3时,HDFS 的放置策略是: 如果写入器在数据阳极上,将一个副本放在本地机器上; 如果写入器在随机数据阳极上,将另一个副本放在不同(远程)机架上的节点上; 如果写入器在同一个远程机架上的不同节点上,将最后一个副本放在不同的节点上。此策略减少机架间写流量,这通常会提高写性能。机架故障的可能性远小于节点故障的可能性; 这种策略不影响数据的可靠性和可用性保证。但是,它确实减少了读取数据时使用的总网络带宽,因为一个块只放在两个独特的机架中,而不是三个。使用此策略,文件的副本不会均匀地分布在机架上。三分之一的副本在一个节点上,三分之二的副本在一个机架上,另外三分之一的副本均匀地分布在剩下的机架上。此策略在不影响数据可靠性或读取性能的情况下提高了写性能。

如果复制因子大于3,则随机确定第4和后续副本的放置位置,同时保持每个机架的副本数量低于上限(基本上是(副本 -1)/机架 + 2)。

因为 NameNode 不允许 datanode 拥有同一块的多个副本,所以当时创建的最大副本数是 datanode 的总数。

在 HDFS 中添加了对存储类型和存储策略的支持之后,NameNode 除了上面描述的机架感知之外,还考虑了这个策略的副本放置。NameNode 首先根据机架感知选择节点,然后检查候选节点是否具有与文件相关联的策略所需的存储空间。如果候选节点没有存储类型,NameNode 将寻找另一个节点。如果在第一个路径中找不到足够的节点来放置副本,NameNode 将在第二个路径中寻找具有回退存储类型的节点。

这里描述的当前的默认副本放置策略正在进行中。

复制选择

为了最小化全局带宽消耗和读延迟,HDFS 尝试满足最接近读取器的副本的读取请求。如果在与读取器节点相同的机架上存在一个副本,那么首选该副本来满足读取请求。如果 HDFS 集群跨越多个数据中心,那么驻留在本地数据中心的副本要优于任何远程副本。

女名女子名

在启动时,NameNode 进入一个名为 Safemode 的特殊状态。当 NameNode 位于 Safemode 状态时,不会复制数据块。NameNode 接收来自 datanode 的 Heartbeat 和 Blockreport 消息。Blockreport 包含 DataNode 托管的数据块列表。每个块具有指定的最小副本数量。当一个数据块的最小副本数已经在 NameNode 中签入时,该块被认为是安全复制的。当一个可配置的百分比的安全复制数据块使用 NameNode 签入后(再加上30秒) ,NameNode 退出 Safemode 状态。然后它确定数据块的列表(如果有的话) ,这些数据块的数目仍然少于指定的副本数。然后 NameNode 将这些块复制到其他 datanode。

文件系统元数据的持久化

HDFS 命名空间由 NameNode 存储。NameNode 使用一个名为 EditLog 的事务日志来持久地记录文件系统元数据发生的每一个更改。例如,在 HDFS 中创建一个新文件会导致 NameNode 将一条记录插入到 EditLog 中,表明这一点。类似地,更改文件的复制因子将导致向 EditLog 插入一条新记录。NameNode 在其本地主机 OS 文件系统中使用一个文件来存储 EditLog。整个文件系统名称空间(包括块到文件和文件系统属性的映射)存储在一个名为 FsImage 的文件中。FsImage 也作为文件存储在 NameNode 的本地文件系统中。

NameNode 在内存中保存了整个文件系统名称空间和文件 Blockmap 的映像。当 NameNode 启动,或者由可配置阈值触发检查点时,它从磁盘读取 FsImage 和 EditLog,将 EditLog 中的所有事务应用于 FsImage 的内存表示,并将这个新版本刷新到磁盘上的新 FsImage。然后,它可以截断旧的 EditLog,因为它的事务已经应用于持久性 FsImage。这个过程称为检查点。检查点的目的是通过获取文件系统元数据的快照并将其保存到 FsImage,确保 HDFS 对文件系统元数据有一致的视图。尽管读取 FsImage 是有效的,但是直接对 FsImage 进行增量编辑是没有效率的。我们没有为每次编辑修改 FsImage,而是将编辑保存在 Editlog 中。在检查点期间,将 Editlog 中的更改应用于 FsImage。检查点可以在以秒表示的给定时间间隔(dfs.namenode.checkpoint.period)或在给定数量的文件系统事务累积(dfs.namenode.checkpoint.txns)后触发。如果设置了这两个属性,则要达到的第一个阈值将触发一个检查点。

DataNode 将 HDFS 数据存储在本地文件系统中的文件中。DataNode 不了解 HDFS 文件。它将每个 HDFS 数据块存储在本地文件系统中的一个单独的文件中。DataNode 不会在同一个目录中创建所有文件。相反,它使用一种启发式方法来确定每个目录的最佳文件数,并适当地创建子目录。在同一个目录中创建所有本地文件并不是最佳选择,因为本地文件系统可能无法有效地支持单个目录中的大量文件。当 DataNode 启动时,它会扫描本地文件系统,生成所有 HDFS 数据块的列表,这些数据块对应于每个本地文件,并将报告发送给 NameNode。这份报告被称为封锁报告。

通信协议

所有 HDFS 通信协议都是在 TCP/IP 协议之上分层的。客户机建立到 NameNode 计算机上可配置的 TCP 端口的连接。它与 NameNode 对话客户端协议。DataNode 使用 DataNode 协议与 NameNode 对话。远程过程调用(RPC)抽象包装了客户端协议和 DataNode 协议。根据设计,NameNode 从不启动任何 rpc。相反,它只响应 DataNodes 或客户机发出的 RPC 请求。

健壮性

HDFS 的主要目标是即使在出现故障时也能可靠地存储数据。三种常见的故障类型是 NameNode 故障、 DataNode 故障和网络分区。

数据磁盘故障、心跳和重复

每个 DataNode 定期向 NameNode 发送 Heartbeat 消息。网络分区可能导致 datanode 的子集失去与 NameNode 的连通性。NameNode 通过缺少 Heartbeat 消息来检测这种情况。NameNode 将最近没有心跳的 DataNodes 标记为已死,并且不向它们转发任何新的 IO 请求。任何注册到已死亡 DataNode 的数据对 HDFS 都不再可用。DataNode 死亡可能导致某些块的复制因子降至指定值以下。NameNode 不断跟踪哪些块需要复制,并在必要时启动复制。由于许多原因,可能需要重新复制: DataNode 可能不可用,副本可能损坏,DataNode 上的硬盘可能失败,或者文件的复制系数可能增加。

标记 DataNodes 已死的超时时间相对较长(默认情况下超过10分钟) ,以避免 DataNodes 的状态振荡导致的复制风暴。用户可以设置更短的间隔,将 DataNodes 标记为陈旧,并避免通过配置性能敏感的工作负载来读写陈旧的节点。

集群再平衡

HDFS 架构与数据重新平衡方案兼容。如果 DataNode 上的空闲空间低于某个阈值,方案可能会自动将数据从一个 DataNode 移动到另一个 DataNode。在突然出现对某个文件的高需求时,一个方案可能会动态地创建额外的副本,并重新平衡集群中的其他数据。这些类型的数据重新平衡方案尚未实现。

数据完整性

从 DataNode 获取的数据块可能已损坏。这种损坏可能是由于存储设备中的错误、网络故障或有缺陷的软件造成的。HDFS 客户端软件实现了 HDFS 文件内容的校验和检查。当客户机创建一个 HDFS 文件时,它计算文件的每个块的校验和,并将这些校验和存储在同一个 HDFS 名称空间中的一个单独的隐藏文件中。当客户端检索文件内容时,它验证从每个 DataNode 接收的数据是否与相关校验和文件中存储的校验和相匹配。如果没有,那么客户端可以选择从另一个具有该块副本的 DataNode 检索该块。

元数据磁盘故障

FsImage 和 EditLog 是 HDFS 的中心数据结构。这些文件的损坏可能导致 HDFS 实例失效。因此,可以将 NameNode 配置为支持维护 FsImage 和 EditLog 的多个副本。对 FsImage 或 EditLog 的任何更新都会导致每个 FsImages 和 EditLogs 得到同步更新。同步更新 FsImage 和 EditLog 的多个副本可能会降低 NameNode 每秒支持的名称空间事务的速度。然而,这种降级是可以接受的,因为尽管 HDFS 应用程序本质上是非常数据密集型的,但它们并不是元数据密集型的。当 NameNode 重新启动时,它选择要使用的最新一致的 FsImage 和 EditLog。

另一个增强对失败的弹性的选择是使用多个 NameNodes 在 NFS 上共享存储或者使用分布式编辑日志(称为 Journal)来启用高可用性。后者是推荐的方法。

快照

快照支持在特定时刻存储数据副本。快照特性的一个用途可能是将损坏的 HDFS 实例回滚到以前已知的良好时间点。

数据组织

数据块

HDFS 设计用于支持非常大的文件。与 HDFS 兼容的应用程序是那些处理大数据集的应用程序。这些应用程序只写入数据一次,但是它们读取数据一次或多次,并且要求这些读取以流的速度满足要求。HDFS 支持对文件进行一次读多写的语义。HDFS 使用的典型块大小为128 MB。因此,HDFS 文件被分割成128 MB 的块,如果可能的话,每个块将驻留在不同的 DataNode 上。

复制流水线

当客户机将数据写入具有三个复制因子的 HDFS 文件时,NameNode 使用复制目标选择算法检索 datanode 列表。此列表包含将托管该块的副本的 DataNodes。然后客户端写入第一个 DataNode。第一个 DataNode 开始接收部分数据,将每个部分写入其本地存储库,并将该部分传输到列表中的第二个 DataNode。第二个 DataNode 依次开始接收数据块的每个部分,将该部分写入其存储库,然后刷新该部分到第三个 DataNode。最后,第三个 DataNode 将数据写入其本地存储库。因此,DataNode 可以从管道中的前一个接收数据,同时将数据转发到管道中的下一个。因此,数据从一个 DataNode 流到下一个 DataNode。

无障碍性

HDFS 可以通过许多不同的方式从应用程序访问。本质上,HDFS 为应用程序提供了一个 filesystemjavaapi。这个 javaapi 和 restapi 的 c 语言包装器也是可用的。此外,HTTP 浏览器也可以用来浏览 HDFS 实例的文件。通过使用 NFS 网关,HDFS 可以挂载为客户端本地文件系统的一部分。

FS Shell

HDFS 允许以文件和目录的形式组织用户数据。它提供了一个叫做 FS shell 的命令行界面,用户可以通过它与 HDFS 中的数据进行交互。这个命令集的语法类似于用户已经熟悉的其他 shell (例如 bash、 csh)。下面是一些动作/命令对的示例:

行动 命令
创建一个名为/foodir Bin/hadoop dfs-mkdir/foodir
删除一个名为/foodir Bin/hadoop fs-rm-r/foodir
查看名为/foodir/myfile.txt bin/hadoop dfs -cat /foodir/myfile.txt

外壳的目标应用程序需要一个脚本语言来与存储的数据进行交互。

发展和管理局

DFSAdmin 命令集用于管理 HDFS 集群。这些命令只能由 HDFS 管理员使用。下面是一些动作/命令对的示例:

行动 命令
把集群放在 Safemode Bin/hdfs dfsadmin-safemode enter
生成一个 DataNodes 列表 Bin/hdfs dfsadmin-报告
重新委托或退役 DataNode (s) Bin/hdfs dfsadmin-refreshNodes

浏览器界面

一个典型的 HDFS 安装配置一个 web 服务器,通过一个可配置的 TCP 端口公开 HDFS 名称空间。这允许用户浏览 HDFS 名称空间并使用 web 浏览器查看其文件的内容。

空间再造

文件删除和取消删除

如果启用了回收站配置,FS Shell 删除的文件不会立即从 HDFS 中删除。相反,HDFS 将其移动到垃圾目录(每个用户在/user/< username >/下有自己的垃圾目录)。垃圾)。只要文件保留在垃圾桶中,就可以快速还原。

最近删除的文件被移动到当前的回收站目录(/user/< username >/)。Trash/Current) ,并且在可配置的时间间隔内,HDFS 创建检查点(在/user/< username >/下)。当前回收站目录中的文件使用 Trash/< date >) ,过期时删除旧的检查点。请参阅 FS shell 中关于检查点的删除命令。

当 NameNode 在垃圾桶中的生命期满后,它将从 HDFS 名称空间中删除该文件。删除文件会释放与文件关联的块。请注意,在用户删除文件的时间和 HDFS 中可用空间相应增加的时间之间可能存在明显的时间延迟。

下面是一个示例,它将显示如何通过 FS Shell 从 HDFS 中删除文件。我们在 delete 目录下创建了2个文件(test1 & test2)

$ hadoop fs -mkdir -p delete/test1
$ hadoop fs -mkdir -p delete/test2
$ hadoop fs -ls delete/
Found 2 items
drwxr-xr-x   - hadoop hadoop          0 2015-05-08 12:39 delete/test1
drwxr-xr-x   - hadoop hadoop          0 2015-05-08 12:40 delete/test2

我们要删除 test1文件。下面的注释显示该文件已经移动到了 Trash 目录。

$ hadoop fs -rm -r delete/test1
Moved: hdfs://localhost:9820/user/hadoop/delete/test1 to trash at: hdfs://localhost:9820/user/hadoop/.Trash/Current

现在我们要删除的文件与 skipTrash 选项,这将不会发送的文件垃圾,它将从 HDFS 完全删除。

$ hadoop fs -rm -r -skipTrash delete/test2
Deleted delete/test2

现在我们可以看到 Trash 目录只包含文件 test1。

$ hadoop fs -ls .Trash/Current/user/hadoop/delete/
Found 1 items\
drwxr-xr-x   - hadoop hadoop          0 2015-05-08 12:39 .Trash/Current/user/hadoop/delete/test1

因此,文件 test1转到 Trash,文件 test2被永久删除。

降低复制因子

当文件的复制因子降低时,NameNode 选择可以删除的多余副本。下一个 Heartbeat 将此信息传输到 DataNode。然后,DataNode 删除相应的块,相应的自由空间出现在集群中。同样,在 setrepledapi 调用完成和集群中的空闲空间出现之间可能存在时间延迟。

posted @ 2021-02-01 20:35  数大招疯-公众号同名  阅读(228)  评论(0编辑  收藏  举报