翻译: http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html
版本:2.9.0
- 介绍
- 假设和目标
- 硬件故障
- 流数据访问
- 大型数据集
- 简单一致性模型
- “移动计算比移动数据便宜”
- 在异构硬件和软件平台上的可移植性
- NameNode和DataNodes
- 文件系统命名空间
- 数据复制
- 副本安置:第一步
- 副本选择
- 安全模式
- 文件系统元数据的持久性
- 通信协议
- 稳健性
- 数据磁盘故障,心跳和重新复制
- 群集重新平衡
- 数据的完整性
- 元数据磁盘失败
- 快照
- 数据组织
- 数据块
- 复制流水线
- 访问操作
- FS Shell
- DFS Admin
- 浏览器接口
- 空间回收
- 文件删除和取消删除
- 降低复制因子
- 参考
介绍
Hadoop分布式文件系统(HDFS)是一种分布式文件系统,设计用于在商品硬件上运行。它与现有的分布式文件系统有许多相似之处。但是,与其他分布式文件系统的差异也很大。HDFS具有高度容错能力,旨在部署在低成本硬件上。HDFS提供对应用程序数据的高吞吐量访问,适用于具有大型数据集的应用程序。HDFS放宽了一些POSIX要求,以启用对文件系统数据的流式访问。HDFS最初是作为Apache Nutch网络搜索引擎项目的基础架构而构建的。HDFS是Apache Hadoop Core项目的一部分。项目URL是http://hadoop.apache.org/。
假设和目标
硬件故障
硬件故障是常态而非例外。一个HDFS实例可能由数百或数千个服务器机器组成,每个服务器都只存储文件系统的部分数据。事实上,有大量的组件,并且每个组件具有不可忽略的失败概率,这意味着HDFS的某个组件始终不起作用的概率非常大。因此,检测故障并快速自动恢复是HDFS的核心架构目标。
流数据访问
在HDFS上运行的应用程序需要流式访问其数据集。它们不是行在通用文件系统上的通用的应用程序 。HDFS的设计更多用于批处理,而不是用户交互式使用。重点是数据访问的高吞吐量,而不是数据访问的低延迟。POSIX强加了HDFS所针对的应用程序所不需要的许多硬性要求。一些关键领域的POSIX语义已被变更用来提高数据吞吐率。
大型数据集
在HDFS上运行的应用程序具有大量数据集。HDFS支持大文件,HDFS中典型文件的大小为千兆字节至兆兆字节。因此应该为单个群集中的数百个节点提供高聚合数据带宽和规模。在单个实例中支持数千万个文件。
简单一致性模型
HDFS应用程序是一个一次写入多次读取的文件访问模型。一旦文件创建,写入和关闭则不再进行其他更改,除了追加和截断之外。支持将内容附加到文件末尾,但不能在任意点附加。这种假设简化了数据一致性问题并实现了高吞吐量数据访问。MapReduce应用程序或Web爬行器应用程序完全符合此模型。
“移动计算比移动数据便宜”
如果应用程序在其操作的数据附近执行,则应用程序所请求的计算效率会更高。当数据集的大小很大时尤其如此。这可以最大限度地减少网络拥塞并提高系统的整体吞吐量。我们的假设是,将计算迁移到更接近数据所在的位置通常会更好,而不是将数据移动到应用程序正在运行的位置。HDFS为应用程序提供接口,使它们更接近数据所在的位置。
在异构硬件和软件平台上的可移植性
HDFS的设计很容易从一个平台移植到另一个平台。这有利于处理大数据量的应用采用HDFS平台。
NameNode和DataNodes
HDFS具有主/从架构。一个HDFS集群包含一个NameNode(一个主服务器),用于管理文件系统名称空间并管理客户端对文件的访问。此外,还有许多DataNode,通常是群集中的每个节点一个DataNode,用于数据存储。HDFS对外暴露文件系统名称空间并允许用户数据存储在文件中。在内部,文件被分成一个或多个块,这些块存储在一组DataNode中。NameNode执行文件系统命名空间操作,如打开,关闭和重命名文件和目录。它还确定块到DataNode的映射。DataNode负责提供来自文件系统客户端的读取和写入请求。DataNode还在NameNode的指令下执行块创建,删除,复制。
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旨在可靠地在大型群集中的机器上存储超大型文件。它将每个文件存储为一系列的块。文件的块被复制以实现容错。块大小和复制因子可以针对每个文件进行配置。
一个文件中除最后一个块之外的所有块都具有相同的大小,而用户可以在最后一个块未达到所配置的块大小的情况下启动新块。
应用程序可以指定文件的副本数量。复制因子可以在文件创建时指定,并可以稍后更改。HDFS中的文件是一次写入的(附加和截断除外),并且在任何时候都严格限定只有一个writer。
NameNode做出关于块复制的所有决定。它定期从集群中的每个DataNode接收Heartbeat和Blockreport。收到Heartbeat意味着DataNode运行正常。Blockreport包含DataNode上所有块的列表。
副本放置:第一步
复制品的放置对于HDFS的可靠性和性能至关重要。优化副本位置可将HDFS与大多数其他分布式文件系统区分开来。这是一项需要大量调整和体验的功能。机架感知复制品放置策略的目的是提高数据可靠性,可用性和网络带宽利用率。复制品放置策略的当前实现是朝这个方向的第一步。实施这项政策的短期目标是在生产系统上对其进行验证,更多地了解其行为,并为测试和研究更复杂的策略奠定基础。
大型HDFS实例通常运行在有多个机架上的一组计算机上。不同机架中两个节点之间的通信必须通过交换机。在大多数情况下,同一机架中机器之间的网络带宽大于不同机架中机器之间的网络带宽。
NameNode通过Hadoop Rack Awareness中描述的过程确定每个DataNode所属的机架标识。一个简单但非最佳的策略是将副本放在独特的机架上。这可以防止整个机架出现故障时丢失数据,并允许在读取数据时从多个机架使用带宽。此策略在集群中均匀分配副本,以便轻松平衡组件故障时的负载。但是,此策略会增加写入成本,因为写入需要将块传输到多个机架。
对于常见情况,如果复制因子为3,则HDFS的放置策略是在本地机器上放置一个副本(如果写入器位于datanode上),否则放置在随机数据节点上;第二个副本复制在另一个远程机架的节点上,最后一个副本放在与第一个副本存放节点相同的机架上的其他节点上。该策略可以减少机架间写入流量,这通常会提高写入性能。机架故障的机会远远小于节点故障的机会; 此策略不会影响数据可靠性和可用性保证。但是,它确实降低了读取数据时使用的总体网络带宽,因为块仅放置在两个独特的机架中,而不是三个。使用此策略,文件的副本不会均匀分布在机架上。三分之一的副本位于一个节点,三分之二的副本位于一个机架上,另外三分之一均匀分布在其余机架上。此策略可提高写入性能,而不会影响数据可靠性或读取性能。
如果复制因子大于3,则随机确定第4个副本和后续副本的位置,同时将每个机架的副本数保持在上限以下((replicas - 1) / racks + 2)。
由于NameNode不允许一个DataNode具有同一个块的多个副本,因此创建的最大副本数是当时的DataNode总数。
在对HDFS添加了对存储类型和存储策略的支持后,除了上述的机架认知之外,NameNode还将副本放置的策略考虑在内。NameNode首先选择基于机架感知的节点,然后检查候选节点是否具有所需的存储空间。如果候选节点不具有,NameNode会查找另一个节点。如果在第一个路径中找不到足够的节点来放置副本,则NameNode将在第二个路径中查找具有回退存储类型的节点。
此处描述的当前默认副本放置策略是一项正在进行的工作。
副本选择
为了尽量减少全局带宽消耗和读取延迟,HDFS会尝试选择最接近读请求的块。如果在读节点的同一机架上存在副本,则该副本优先满足读取请求。如果HDFS群集跨越多个数据中心,则驻留在本地数据中心的副本优先于任何远程副本。
安全模式
在启动时,NameNode进入一个称为Safemode的特殊状态。当NameNode处于安全模式状态时,不会发生数据块的复制。NameNode接收来自DataNode的Heartbeat和Blockreport消息。Blockreport包含DataNode托管的数据块列表。每个块都具有副本的最小数量值。如果NameNode检测到该数据块达到要求的最小副本数,则认为该块已被安全的复制了。当已被安全复制块的百分比达到一定值(再加上30秒)之后,NameNode退出安全模式状态。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。该报告称为Blockreport。
通信协议
所有HDFS通信协议都在TCP / IP协议之上 。客户端建立到NameNode机器上可配置TCP端口的连接,它与NameNode使用ClientProtocol通讯。DataNode使用DataNode协议与NameNode进行通信。远程过程调用(RPC)包括客户端协议和数据节点协议。根据设计,NameNode永远不会启动任何RPC。相反,它只响应DataNode或客户端发出的RPC请求。
稳健性(Robustness)
HDFS的主要目标是即使在出现故障时也能可靠地存储数据。三种常见类型的故障是NameNode故障,DataNode故障和网络故障。
数据磁盘故障,心跳和重新复制
每个DataNode定期向NameNode发送一个Heartbeat消息。网络故障可能导致DataNode的一个子集失去与NameNode的连接。NameNode通过Heartbeat消息来检测这种情况。NameNode将最近没有Heartbeats的DataNode标记为死亡,并且不会向它们转发任何新的IO请求。任何注册到死亡DataNode的数据将不再可用。DataNode死亡可能导致某些块的复制因子降到其指定值以下。NameNode会不断跟踪哪些块需要复制,并在需要时启动复制。重新复制的必要性可能由于以下原因而产生:DataNode可能变得不可用,副本可能会损坏,DataNode上的硬盘可能会损坏,或者文件的复制因子增大。
标记DataNode死亡的超时时间比较长(默认情况下超过10分钟),以避免由DataNode的状态震荡引起的复制风暴。用户可以设置较短的时间间隔,以避免在读取和/或写入性能敏感工作时出现问题。
群集重新平衡
HDFS架构与数据重新平衡方案兼容。如果DataNode上的可用空间低于某个阈值,则文件系统可能会自动将数据从一个DataNode移动到另一个DataNode。在特定文件突然高需求的情况下,可能会动态创建额外的副本并重新平衡群集中的其他数据。这些类型的数据重新平衡方案尚未实施。
数据的完整性
从DataNode获取的数据块可能会损坏。可能会发生此损坏的原因包括存储设备故障,网络故障或软件错误。HDFS客户端软件对HDFS文件的内容执行校验和检查。当客户端创建HDFS文件时,它会计算文件每个块的校验和,并将这些校验和存储在同一个HDFS名称空间中的单独隐藏文件中。当客户端检索文件内容时,它会验证从每个DataNode收到的数据是否与存储在相关校验和文件中的校验和相匹配。如果不是,那么客户端可以选择从另一个具有该块的副本的DataNode中检索该块。
元数据磁盘失败
FsImage和EditLog是HDFS的中心数据结构。这些文件的损坏可能会导致HDFS实例失效。由于这个原因,NameNode可以配置为支持维护FsImage和EditLog的多个副本。对FsImage或EditLog的任何更新都会导致每个FsImages和EditLog同步更新。同步更新FsImage和EditLog的多个副本可能会降低NameNode每秒可支持的名称空间事务处理速度。但是,这种降级是可以接受的,因为即使HDFS应用程序本质上是非常密集的数据,它们也不是元数据密集型的(没看懂,应该是应用程序数据不如元数据重要)。当NameNode重新启动时,它会选择最新的一致的FsImage和EditLog来使用。
另一个增加弹性以抵御故障的方法是使用多个NameNode启用高可用性,使用NFS上的共享存储或使用分布式编辑日志(称为日记)。后者是推荐的方法。
快照
快照支持在特定时刻存储数据副本。快照功能的一种用法可能是将损坏的HDFS实例回滚到先前已知的良好时间点。
数据组织
数据块
HDFS旨在支持非常大的文件。与HDFS兼容的应用程序是处理大型数据集的应用程序。这些应用程序只写入其数据一次,但他们读取一次或多次,并要求在流速下读取。HDFS支持在文件上一次写入多次读取语义。HDFS使用的典型块大小为128 MB。因此,一个HDFS文件被分成128 MB块,如果可能的话,每个块将驻留在不同的DataNode上。
复制流水线
当客户端将数据写入复制因子为3的HDFS文件时,NameNode使用复制目标选择算法检索DataNode列表。该列表包含将承载该块的副本的DataNodes。客户端然后写入第一个DataNode。第一个DataNode开始接收部分数据,将每个部分写入其本地存储库并将该部分传输到列表中的第二个DataNode。第二个DataNode也开始接收数据块的每个部分,将该部分写入其存储库,然后将该部分传输到第三个DataNode。最后,第三个DataNode将数据写入其本地存储库。因此,DataNode可以从流水线中的前一个接收数据,并且同时将数据转发到流水线中的下一个数据。从而,数据是以流水线的方式从一个datanode传输到下一个。
无障碍
HDFS可以通过许多不同的访问方式。从本质上讲,HDFS 为应用程序提供了一个FileSystem Java API。C语言包封装API和REST API也是可用的。另外还有一个HTTP浏览器,也可以用来浏览HDFS实例的文件。通过使用NFS网关,可以将HDFS挂载为本地文件系统的一部分。
FS Shell
HDFS允许用户数据以文件和目录的形式进行组织。它提供了一个名为FS shell的命令行界面,可让用户与HDFS中的数据进行交互。这个命令集的语法类似于用户已经熟悉的其他shell(例如bash,csh)。以下是一些示例操作/命令对:
FS外壳针对需要脚本语言与存储数据进行交互的应用程序。
DFSAdmin
DFSAdmin命令集用于管理HDFS集群。这些是仅由HDFS管理员使用的命令。以下是一些示例操作/命令对:
浏览器界面
典型的HDFS将安装配置一个Web服务器公开HDFS名称空间。这允许用户使用Web浏览器浏览HDFS名称空间并查看其文件。
空间回收
文件删除和取消删除
如果启用垃圾箱配置,FS Shell删除的文件不会立即从HDFS中删除。相反,HDFS将其移动到垃圾目录(每个用户在< /user/
最近删除的文件移动到当前的垃圾目录( /user/
在废物生命周期结束后,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。下面的注释显示该文件已被移至垃圾箱目录。
$ hadoop fs -rm -r delete/test1
Moved: hdfs://localhost:8020/user/hadoop/delete/test1 to trash at: hdfs://localhost:8020/user/hadoop/.Trash/Current
现在我们将使用skipTrash选项删除文件,该选项不会将文件发送到垃圾箱。它将从HDFS中完全删除。
$ hadoop fs -rm -r -skipTrash delete/test2
Deleted delete/test2
我们现在可以看到垃圾目录仅包含文件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进入垃圾箱,文件test2被永久删除。
降低复制因子
当文件的复制因子减少时,NameNode选择可以删除的多余副本。下一个Heartbeat将此信息传输到DataNode。DataNode然后删除相应的块,并在群集中出现相应的可用空间。再一次,setReplication API调用完成和群集中可用空间的出现之间可能存在时间延迟。
参考
Hadoop JavaDoc API。
HDFS源代码:http://hadoop.apache.org/version_control.html