介绍
Hadoop分布式文件系统( <acronym title="Hadoop分布式文件系统" style="cursor: help;">HDFS</acronym> )是一种分布式文件系统,设计用于在商品硬件上运行。它与现有的分布式文件系统有许多相似之处。但是,与其他分布式文件系统的差异很大。HDFS具有高度容错能力,旨在部署在低成本硬件上。HDFS提供对应用程序数据的高吞吐量访问,适用于具有大型数据集的应用程序。HDFS放宽了一些POSIX要求,以启用对文件系统数据的流式访问。HDFS最初是作为Apache Nutch网络搜索引擎项目的基础架构而构建的。HDFS现在是一个Apache Hadoop子项目。项目URL是http://hadoop.apache.org/hdfs/ 。
假设和目标
硬件故障
硬件故障是常态而非例外。一个HDFS实例可能由数百或数千个服务器机器组成,每个服务器机器都存储部分文件系统的数据。事实上,有大量的组件,并且每个组件具有不可忽略的失败概率,这意味着HDFS的某个组件始终不起作用。因此,检测故障并快速自动恢复是HDFS的核心架构目标。
流数据访问
在HDFS上运行的应用程序需要流式访问其数据集。它们不是通常运行在通用文件系统上的通用应用程序。HDFS的设计更多用于批处理,而不是用户交互式使用。重点是数据访问的高吞吐量,而不是数据访问的低延迟。POSIX强加了HDFS所针对的应用程序所不需要的许多硬性要求。一些关键领域的POSIX语义已被舍弃以提高数据吞吐率。
大型数据集
在HDFS上运行的应用程序具有大量数据集。HDFS中的典型文件大小为千兆字节(gigabytes)至兆兆字节(terabytes)。因此,HDFS被调整为支持大文件。它应该为单个群集中的数百个节点提供高聚合数据带宽和规模(high aggregate data bandwidth and scale)。它应该支持单个实例中的数千万个文件。
简单一致性模型
HDFS应用程序需要一次写入多次读取多个文件访问模型。一次创建,写入和关闭的文件不需要更改。这种假设简化了数据一致性问题并实现了高吞吐量数据访问。MapReduce应用程序或Web爬虫应用程序完全符合此模型。有一个计划来支持未来对文件的追加写入。
“移动计算比移动数据便宜”
如果应用程序在其操作的数据附近执行,则应用程序所请求的计算效率会更高。当数据集的大小很大时尤其如此。这可以最大限度地减少网络拥塞并提高系统的整体吞吐量。我们的假设是,将计算迁移到更接近数据所在的位置通常会更好,而不是将数据移动到应用程序正在运行的位置。HDFS为应用程序提供接口,使它们更接近数据所在的位置。
跨异构硬件和软件平台的可移植性
HDFS的设计很容易从一个平台移植到另一个平台。这有利于广泛采用HDFS作为大量应用选择的平台。
NameNode和DataNodes
HDFS具有主/从架构。一个HDFS集群包含一个NameNode,一个主服务器,用于管理文件系统名称空间并管理客户端对文件的访问。此外,还有许多DataNode,通常是群集中的每个节点一个DataNode,用于管理连接到它们所运行的节点的存储。HDFS公开文件系统名称空间并允许用户数据存储在文件中。在内部,文件被分成一个或多个块,这些块存储在一组DataNode中。NameNode执行文件系统命名空间操作,如打开,关闭和重命名文件和目录。它还确定块到DataNode的映射。DataNode负责提供来自文件系统客户端的读取和写入请求。DataNode还根据来自NameNode的指令执行数据块创建,删除和复制。
NameNode和DataNode是设计用于在商品机器上运行的软件。这些机器通常运行GNU / Linux操作系统( <acronym title="操作系统" style="cursor: help;">OS</acronym> )。HDFS使用Java语言构建;任何支持Java的机器都可以运行NameNode或DataNode软件。使用高度可移植的Java语言意味着HDFS可以部署在各种机器上。典型的部署有一台只运行NameNode软件的专用机器。群集中的每台其他机器运行DataNode软件的一个实例。该体系结构不排除在同一台计算机上运行多个DataNode,但在实际部署中很少出现这种情况。
集群中单个NameNode的存在极大地简化了系统的体系结构。NameNode是所有HDFS元数据的仲裁者和存储库。该系统的设计方式是用户数据永远不会流经NameNode。
文件系统命名空间
HDFS支持传统的分层文件组织。用户或应用程序可以在这些目录内创建目录并存储文件。文件系统名称空间层次与大多数其他现有文件系统类似;可以创建和删除文件,将文件从一个目录移动到另一个目录,或者重命名文件。HDFS尚未实现用户配额。HDFS不支持硬链接或软链接。但是,HDFS体系结构并不排除实现这些功能。
NameNode维护文件系统名称空间。NameNode记录对文件系统名称空间或其属性的任何更改。应用程序可以指定HDFS应该维护的文件的副本数量。文件的副本数称为该文件的复制因子。这些信息由NameNode存储。
数据复制
HDFS旨在可靠地在大型群集中的机器上存储超大型文件。它将每个文件存储为一系列的块;文件中除最后一个块之外的所有块都具有相同的大小。文件的块被复制以实现容错。块大小和复制因子可以针对每个文件进行配置。应用程序可以指定文件的副本数量。可以在文件创建时指定复制因子,并可稍后进行更改。HDFS中的文件是一次写入的,并且在任何时候都严格限定一个写入者。
NameNode做出关于块复制的所有决定。它定期从集群中的每个DataNode接收Heartbeat和Blockreport。收到Heartbeat意味着DataNode运行正常。Blockreport包含DataNode上所有块的列表。
复制品安置:第一个婴儿步骤
复制品的放置对于HDFS的可靠性和性能至关重要。优化副本位置可将HDFS与大多数其他分布式文件系统区分开来。这是一项需要大量调整和体验的功能。机架感知复制品放置策略(rack-aware replica placement policy)的目的是提高数据可靠性,可用性和网络带宽利用率。复制品放置策略的当前实现是朝这个方向的第一步。实施这项策略的短期目标是在生产系统上对其进行验证,更多地了解其行为,并为测试和研究更复杂的策略奠定基础。
大型HDFS实例运行在通常分布在多个机架上的一组计算机上。不同机架中两个节点之间的通信必须通过交换机。在大多数情况下,同一机架中机器之间的网络带宽大于不同机架中机器之间的网络带宽。
NameNode通过Hadoop Rack Awareness中概述的过程确定每个DataNode所属的机架标识。一个简单但非最佳的策略是将副本放在不同的机架上。这可以防止整个机架出现故障时丢失数据,并允许在读取数据时从多个机架使用带宽。此策略在集群中均匀分配副本,以便轻松平衡组件故障时的负载。但是,此策略会增加写入成本,因为写入需要将块传输到多个机架。
对于常见情况,当复制因子为3时,HDFS的放置策略是将一个副本放在本地机架中的一个节点上,另一个放在另一个(远程)机架中的节点上,并将最后一个放在相同的远程机架的不同节点上。该策略可以减少机架间写入流量,这通常会提高写入性能。机架故障的机会远远小于节点故障的机会;此策略不会影响数据可靠性和可用性保证。但是,它确实降低了读取数据时使用的总体网络带宽,因为块仅放置在两个不同的机架中,而不是三个。使用此策略,文件的副本不会均匀分布在机架上。三分之一的副本位于一个节点上,三分之二的副本位于一个机架上,另外三分之一的副本均匀分布在其余机架上。此策略可提高写入性能,而不会影响数据可靠性或读取性能。
此处描述的当前默认副本放置策略是一项正在进行的工作。
副本选择
为了最大限度地降低全局带宽消耗和读取延迟,HDFS会尝试满足最接近读者的副本的读取请求。如果在读者节点的同一机架上存在副本,则该副本优先满足读取请求。如果HDFS集群跨越多个数据中心,则驻留在本地数据中心的副本优先于任何远程副本。
安全模式
在启动时,NameNode进入一个称为Safemode的特殊状态。当NameNode处于安全模式状态时,不会发生数据块的复制。NameNode接收来自DataNode的Heartbeat和Blockreport消息。Blockreport包含DataNode托管的数据块列表。每个块都有指定的最小数量的副本。当该数据块的最小副本数已与NameNode签入时,该块被认为是安全复制的。在安全复制数据块的可配置百分比签入NameNode(再加上30秒)之后,NameNode退出安全模式状态。然后确定(如果有的话)仍然少于指定的副本数量的数据块的列表。NameNode然后将这些块复制到其他DataNode。
文件系统元数据的持久性
HDFS名称空间由NameNode存储。NameNode使用名为EditLog的事务日志来持久记录文件系统元数据发生的所有更改。例如,在HDFS中创建一个新文件会导致NameNode向EditLog中插入一条记录,指出这一点。同样,更改文件的复制因子会导致将新记录插入到EditLog中。NameNode使用其本地主机OS文件系统中的文件来存储EditLog。整个文件系统名称空间(包括块到文件和文件系统属性的映射)存储在名为FsImage的文件中。FsImage也作为文件存储在NameNode的本地文件系统中。
NameNode将整个文件系统名称空间和文件Blockmap的映像保存在内存中。这个关键的元数据项目设计得很紧凑,这样一个具有4GB RAM的NameNode足以支持大量的文件和目录。当NameNode启动时,它从磁盘读取FsImage和EditLog,将EditLog中的所有事务应用到FsImage的内存中表示,并将此新版本刷新到磁盘上的新FsImage中。它可以截断旧的EditLog,因为它的事务已经被应用到持久的FsImage。这个过程被称为检查点。在当前的实现中,只有在NameNode启动时才会出现检查点。正在开展工作以支持不久的将来的定期检查点。
DataNode将HDFS数据存储在本地文件系统中的文件中。DataNode没有关于HDFS文件的知识。它将每个HDFS数据块存储在本地文件系统中的单独文件中。DataNode不会在同一目录中创建所有文件。相反,它使用启发式来确定每个目录的最佳文件数量并适当地创建子目录。在同一目录中创建所有本地文件并不是最佳选择,因为本地文件系统可能无法有效地支持单个目录中的大量文件。当DataNode启动时,它扫描其本地文件系统,生成与每个本地文件相对应的所有HDFS数据块的列表,并将此报告发送给NameNode:这是Blockreport。
通信协议
所有HDFS通信协议都在TCP / IP协议之上进行分层。客户端建立到NameNode机器上可配置<acronym title="传输控制协议" style="cursor: help;">TCP</acronym>端口的连接。它与NameNode按照ClientProtocol交谈。DataNode使用DataNode协议与NameNode进行通信。远程过程调用( <acronym title="远程过程调用" style="cursor: help;">RPC</acronym> )抽象包装了客户端协议和DataNode协议。根据设计,NameNode永远不会启动任何RPC。相反,它只响应DataNode或客户端发出的RPC请求。
稳健性
HDFS的主要目标是即使在出现故障时也能可靠地存储数据。三种常见类型的故障是NameNode故障,DataNode故障和网络分区。
数据磁盘故障,心跳和重新复制
每个DataNode定期向NameNode发送一个Heartbeat消息。网络分区可能会导致一部分DataNode失去与NameNode的连接。NameNode通过缺少Heartbeat消息来检测这种情况。NameNode将没有最近Heartbeats的DataNode标记为死亡,并且不会向它们转发任何新的<acronym title="输入输出" style="cursor: help;">IO</acronym>请求。任何注册到死亡DataNode的数据不再可用于HDFS。DataNode死亡可能导致某些块的复制因子降到其指定值以下。NameNode会不断跟踪哪些块需要复制,并在需要时启动复制。重新复制的必要性可能由于许多原因而产生:DataNode可能变得不可用,副本可能会损坏,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机器是HDFS群集的单点故障。如果NameNode机器出现故障,则需要手动干预。目前,不支持NameNode软件自动重新启动和故障切换到另一台机器。
快照
快照支持在特定时刻存储数据副本。快照功能的一种用法可能是将损坏的HDFS实例回滚到先前已知的良好时间点。HDFS目前不支持快照,但将在未来的版本中支持。
数据组织
数据块
HDFS旨在支持非常大的文件。与HDFS兼容的应用程序是处理大型数据集的应用程序。这些应用程序只写入其数据一次,但他们读取一次或多次,并要求在流速下满足这些读取。HDFS支持在文件上一次写入多次读取语义。HDFS使用的典型块大小为64 MB。因此,HDFS文件被分成64 MB的块,如果可能的话,每个块将驻留在不同的DataNode上。
分期(Staging)
客户端创建文件的请求不会立即到达NameNode。实际上,HDFS客户端最初将文件数据缓存到临时本地文件中。应用程序写入被透明地重定向到这个临时的本地文件。当本地文件累积超过一个HDFS块大小的数据时,客户端会联系NameNode。NameNode将文件名插入到文件系统层次结构中,并为其分配一个数据块。NameNode用DataNode的标识和目标数据块响应客户请求。然后客户端将本地临时文件中的数据块刷新到指定的DataNode。当文件关闭时,临时本地文件中剩余的未刷新数据将传输到DataNode。客户端然后告诉NameNode文件已关闭。此时,NameNode将文件创建操作提交到持久存储区。如果NameNode在文件关闭之前死亡,则文件丢失。
在仔细考虑在HDFS上运行的目标应用程序后,采用了上述方法。这些应用程序需要流式写入文件。如果客户端在没有任何客户端缓冲的情况下直接写入远程文件,则网络速度和网络拥塞会严重影响吞吐量。这种做法并非没有先例。早期的分布式文件系统(例如<acronym title="安德鲁(Andrew)文件系统" style="cursor: help;">AFS</acronym> )使用客户端缓存来提高性能。POSIX的要求已经放宽,以实现更高的数据上传性能。
复制流水线
当客户端将数据写入HDFS文件时,首先将数据写入本地文件,如前一节所述。假设HDFS文件的复制因子为3。当本地文件累积完整的用户数据块时,客户端从NameNode中检索DataNode列表。该列表包含将承载该块的副本的DataNode。客户端然后将数据块刷新到第一个DataNode。第一个DataNode开始以小部分(4 KB)接收数据,将每个部分写入其本地存储库并将该部分传输到列表中的第二个DataNode。第二个DataNode反过来开始接收数据块的每个部分,将该部分写入其存储库,然后将该部分刷新到第三个DataNode。最后,第三个DataNode将数据写入其本地存储库。因此,DataNode可以从流水线中的前一个接收数据,并且同时将数据转发到流水线中的下一个数据。因此,数据从一个DataNode流水到下一个。
无障碍(Accessibility)
HDFS可以通过许多不同的方式从应用程序中访问。从本质上讲,HDFS为应用程序提供了一个Java API 。此Java API的C语言包装器也可用。另外,还可以使用HTTP浏览器浏览HDFS实例的文件。正在进行工作,通过<acronym title="基于Web的分布式创作和版本控制" style="cursor: help;">WebDAV</acronym>协议公开HDFS。
FS Shell
HDFS允许用户数据以文件和目录的形式组织。它提供了一个名为FS shell的命令行界面,可让用户与HDFS中的数据进行交互。这个命令集的语法类似于用户已经熟悉的其他shell(例如bash,csh)。以下是一些示例操作/命令对:
| 行动 | 命令 |
| 创建一个名为/ foodir的目录 | bin / hadoop dfs -mkdir / foodir |
| 删除名为/ foodir的目录 | bin / hadoop dfs -rmr / foodir |
| 查看名为/foodir/myfile.txt的文件的内容 | bin / hadoop dfs -cat /foodir/myfile.txt |
FS Shell针对需要脚本语言与存储数据进行交互的应用程序。
DFSAdmin
DFSAdmin命令集用于管理HDFS集群。这些是仅由HDFS管理员使用的命令。以下是一些示例操作/命令对:
| 行动 | 命令 |
| 将群集置于Safemode | bin / hadoop dfsadmin -safemode进入 |
| 生成DataNode列表 | bin / hadoop dfsadmin -report |
| 重新投放或停用DataNode(s) | bin / hadoop dfsadmin -refreshNodes |
浏览器界面
典型的HDFS安装将Web服务器配置为通过可配置的TCP端口公开HDFS名称空间。这允许用户使用Web浏览器浏览HDFS名称空间并查看其文件的内容。
空间回收
文件删除和取消删除
当文件被用户或应用程序删除时,它不会立即从HDFS中删除。相反,HDFS首先将其重命名为/ trash目录中的文件。只要文件保持在/垃圾箱中,该文件可以快速恢复。文件保留在/垃圾箱中一段可配置的时间。在/ trash中生命期满后,NameNode将文件从HDFS名称空间中删除。删除文件会导致与文件关联的块被释放。请注意,用户删除文件的时间与HDFS中相应增加可用空间的时间之间可能存在明显的时间延迟。
用户可以在删除文件后取消删除文件,只要文件保留在/ trash目录中即可。如果用户想要取消删除他/她已删除的文件,他/她可以浏览/垃圾目录并检索文件。/ trash目录仅包含已删除文件的最新副本。/ trash目录就像具有一个特殊功能的任何其他目录一样:HDFS应用指定策略自动从该目录中删除文件。当前的默认策略是从/垃圾桶中删除超过6个小时的文件。将来,这个策略将通过一个定义良好的界面进行配置。
降低复制因子
当文件的复制因子减少时,NameNode选择可以删除的多余副本。下一个Heartbeat将此信息传输到DataNode。DataNode然后删除相应的块,并在群集中出现相应的可用空间。再一次, setReplication API调用完成和群集中可用空间的出现之间可能存在时间延迟。
参考
HDFS Java API: http : //hadoop.apache.org/core/docs/current/api/
HDFS源代码: http : //hadoop.apache.org/hdfs/version_control.html
由Dhruba Borthakur提供