Hadoop分布式文件系统(HDFS)是一种分布式文件系统,用于在普通商用硬件上运行。它与现有的分布式文件系统有许多类似之处。然而,与其余分布式文件系统的区别很大。HDFS具备高度的容错能力,旨在部署在低成本的硬件上。HDFS提供对应用程序数据的高吞吐量访问,适用于具备大数据集的应用程序。HDFS放宽了一些POSIX要求,以便对文件系统数据进行流式访问。HDFS最初是做为Apache Nutch Web搜索引擎项目的基础架构构建的。HDFS是Apache Hadoop Core项目的一部分。http://hadoop.apache.org/html
硬件故障很常见而不例外。HDFS实例能够由数百或数千台服务器机器组成,每台服务器存储部分文件系统的数据。事实上,有大量的组件,而且每一个组件具备不必定的故障几率,这意味着HDFS的某些组件老是不起做用的。所以,故障检测和快速自动恢复是HDFS的核心架构。node
在HDFS上运行的应用程序须要对其数据集进行流式访问。HDFS不是用于提供普通应用访问的文件系统。HDFS的设计更多用于批量处理,而不是用户的交互式使用。重点是数据访问的高吞吐量,而不是数据访问的低延迟。POSIX施加了许多难于为HDFS定位的应用程序所需的硬要求。POSIX语义在几个关键领域已被交易,以提升数据吞吐率。shell
在HDFS上运行的应用程序具备较大的数据集。HDFS中的典型文件大小为千兆字节。所以,HDFS被调整为支持大文件。它应该提供高聚合数据带宽并扩展到单个集群中的数百个节点。它应该在一个实例中支持数千万个文件。apache
HDFS数据访问模式为一次写入屡次读取。文件一旦建立、写入和关闭后,除了追加和截断,文件内容再也不变化。将内容附加到文件的末尾是受支持的,但不能随意更新。该假设简化了数据一致性问题,并实现了高吞吐量数据访问。MapReduce应用程序或Web爬虫程序应用程序与此模型完美匹配。api
若是应用程序可以很近德运行在其须要的数据,则应用程序所请求的计算效率更高【应用处理本机数据比远程数据更快】。当数据集很大时,这一点尤为如此。这样能够最大限度地减小网络拥塞并提升系统的总体吞吐量。假设一般更好地将计算迁移到更接近数据位置的位置,而不是将数据移动到应用程序运行的位置。HDFS为应用程序提供接口,使其更接近数据所在的位置。浏览器
HDFS被设计为能够从一个平台轻松地移植到另外一个平台。这有助于HDFS做为大型应用程序的首选平台。缓存
HDFS具备主/从结构。HDFS集群包含单一的NameNode做为master服务器,用于管理文件系统命名空间,并调节客户端对文件的访问。此外,还有一些DataNodes,一般是集群中每一个节点的一个,它们管理链接到运行的节点的存储。HDFS公开了文件系统命名空间,并容许将用户数据存储在文件中。在内部,文件被分割成一个或多个块,而且这些块被存储在一组DataNodes中。NameNode执行文件系统命名空间操做,如打开,关闭和重命名文件和目录。它还肯定块到DataNodes的映射。DataNodes负责从文件系统的客户端提供读取和写入请求。DataNode还能够根据NameNode的指示执行块建立,删除和复制。安全
NameNode和DataNode是用于在商用机上运行的软件。这些机器一般运行GNU / Linux操做系统(OS)。HDFS使用Java语言构建;任何支持Java的机器均可以运行NameNode或DataNode软件。高度可移植的Java语言的使用意味着HDFS能够部署在普遍的机器上。典型的部署具备仅运行NameNode软件的专用机器。集群中的每一个其余计算机都运行DataNode软件的一个实例。该架构并不排除在同一台机器上运行多个DataNodes,而是在不多出现的实际部署中。bash
集群中单个NameNode的存在大大简化了系统的体系结构。NameNode是全部HDFS元数据的仲裁器和存储库。该系统的设计方式使得用户数据不会流经NameNode。服务器
HDFS支持传统的分层文件组织。用户或应用程序能够建立目录并将文件存储在这些目录中。文件系统命名空间层次结构与大多数其余现有文件系统相似;能够建立和删除文件,将文件从一个目录移动到另外一个目录,或者重命名文件。HDFS支持用户配额和访问权限。HDFS不支持硬连接或软连接。然而,HDFS架构并不排除实现这些功能。
NameNode维护文件系统命名空间。文件系统名称空间或其属性的任何更改都由NameNode记录。应用程序能够指定应由HDFS维护的文件的副本数。文件的副本数称为该文件的复制因子。该信息由NameNode存储。
HDFS设计用于在大型集群中的机器之间可靠地存储很是大的文件。它将每一个文件存储为一系列块。复制文件的块以进行容错。块大小和复制因子是可配置的每一个文件。【hdfs-site.xml dfs.block.size dfs.replication】
除了最后一个块以外的文件中的全部块都是相同的大小,而用户能够在将可变长度块的支持添加到追加和hsync以后启动一个新的块,而不会将最后一个块填充到配置的块大小。
应用程序能够指定文件的副本数。能够在文件建立时指定复制因子,稍后更改。HDFS中的文件是一次写入(除了附加和截断以外),而且在任什么时候候都有一个做者。
NameNode作出关于块复制的全部决定。它周期性地从集群中的每一个DataNode接收到一个心跳和一个阻塞报告。收到心跳意味着DataNode正常运行。Blockreport包含DataNode上全部块的列表。
复制品的放置对于HDFS的可靠性和性能相当重要。优化复制放置将HDFS与大多数其余分布式文件系统区分开来。这是一个须要大量调整和体验的功能。机架感知复制放置策略的目的是提升数据可靠性,可用性和网络带宽利用率。目前的复制放置政策的实施是朝这个方向努力的第一步。实施这一政策的短时间目标是在生产系统上进行验证,更多地了解其行为,并为更复杂的政策进行测试和研究奠基基础。
大型HDFS实例在一般分布在多个机架上的计算机集群上运行。不一样机架中的两个节点之间的通讯必须通过交换机。在大多数状况下,同一机架中的机器之间的网络带宽大于不一样机架中的机器之间的网络带宽。
NameNode经过Hadoop机架意识【http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/RackAwareness.html】中概述的过程来肯定每一个DataNode所属的机架ID。一个简单但不是最优的策略是将副本放在独特的机架上。这能够防止整个机架发生故障时丢失数据,并容许在读取数据时使用多个机架的带宽。该策略在集群中均匀分配副本,这使得轻松平衡组件故障时的负载。可是,这种策略会增长写入的成本,由于写入须要将块传输到多个机架。
对于常见状况,当复制因子为3时,HDFS的放置策略是将一个副本放在本地机架中的一个节点上,另外一个在本地机架上的另外一个节点上,最后在不一样机架中的不一样节点上。该策略能够减小机架间的写入流量,这一般会提升写入性能。机架故障的机会远小于节点故障的机会;此政策不影响数据的可靠性和可用性保证。然而,它确实减小了在读取数据时使用的整体网络带宽,由于块仅放置在两个独特的机架中,而不是三个。使用此策略,文件的副本不会均匀分布在机架中。三分之一的副本在一个节点上,三分之二的副本在一个机架上,另外三个是均匀分布在剩余的机架上。此策略可改善写入性能,而不会影响数据的可靠性或读取性能。
若是复制因子大于3,则随机肯定第4个和之后副本的位置,同时保持每一个机架的副本数量低于上限(基本为(复制1)/机架2))。
因为NameNode不容许DataNodes具备相同块的多个副本,因此建立的副本的最大数目是当时的DataNodes的总数。
在将存储类型和存储策略【http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/ArchivalStorage.html】的支持添加到HDFS以后,除了上述的机架感知以外,NameNode还会将策略考虑在副本位置。NameNode首先根据机架识别选择节点,而后检查候选节点是否具备与文件关联的策略所需的存储。若是候选节点没有存储类型,则NameNode将查找另外一个节点。若是在第一个路径中找不到足够的放置副本的节点,则NameNode将在第二个路径中查找具备备用存储类型的节点。
此处描述的当前,默认的复制放置策略是一项正在进行的工做。
为了最大限度地减小全局带宽消耗和读取延迟,HDFS会尝试从最接近读卡器的副本获取读取请求。若是在与读取器节点相同的机架上存在副本,则该副本优选知足读取请求。若是HDFS群集跨越多个数据中心,则驻留在本地数据中心的副本优先于任何远程副本。
在启动时,NameNode进入一个称为Safemode的特殊状态。NameNode处于Safemode状态时,不会复制数据块。NameNode从DataNodes接收心跳和Blockreport消息。Blockreport包含DataNode承载的数据块列表。每一个块具备指定的最小数量的副本。当使用NameNode检入数据块的最小副本数时,块被认为是安全复制的。在可配置百分比的安全复制数据块使用NameNode(加上另外30秒)以后,NameNode退出Safemode状态。而后,它肯定仍然具备少于指定数量的副本的数据块(若是有)的列表。NameNode而后将这些块复制到其余DataNodes。
1.EditLog
2.FsImage
HDFS命名空间由NameNode存储。NameNode使用名为EditLog的事务日志持续记录文件系统元数据发生的每一个更改。例如,在HDFS中建立一个新文件会致使NameNode将一个记录插入到EditLog中。相似地,更改文件的复制因子将致使将新记录插入到EditLog中。NameNode使用其本地主机OS文件系统中的文件来存储EditLog。整个文件系统命名空间(包括将块映射到文件和文件系统属性)存储在一个名为FsImage的文件中。FsImage做为文件存储在NameNode的本地文件系统中。
checkpoint 用于合并EditLog至FsImage,FsImage是文件系统最新的元数据,但不直接更新FsImage,而是定时合并EditLog至FsImage
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端口创建链接。利用ClientProtocol协议与NameNode进行通讯。DataNode使用DataNode协议与NameNode进行通讯。远程过程调用(RPC)抽象包含客户端协议和数据节点协议。按照设计,NameNode从不启动任何RPC。相反,它只响应DataNodes或客户端发出的RPC请求。
HDFS的主要目标是即便存在故障也可以可靠地存储数据。三种常见的故障类型是NameNode故障,DataNode故障和网络分区
每一个DataNode按期向NameNode发送一个心跳信息。网络分区可能致使DataNodes的一个子集与NameNode失去链接。NameNode经过不存在心跳消息来检测此状况。NameNode将DataNodes标记为没有最近的Heartbeats死机,而且不会向其转发任何新的IO请求。任何已注册到死亡数据节点的数据再也不适用于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来使用。
快照支持在特定时刻存储数据副本。快照功能的一个用法多是将损坏的HDFS实例回滚到先前已知的好时间点。
HDFS旨在支持很是大的文件。与HDFS兼容的应用程序是处理大型数据集的应用程序。这些应用程序只写一次数据,但它们读取一次或屡次,并要求这些读取在流速下知足。HDFS支持对文件的一次读取多语义。HDFS使用的典型块大小是128 MB。所以,将HDFS文件切成128 MB块,若是可能,每一个块将驻留在不一样的DataNode上。
建立文件的客户端请求不会当即到达NameNode。实际上,最初,HDFS客户端将文件数据缓存到本地缓冲区中。应用程序写入被透明地重定向到本地缓冲区。当本地文件累积超过一个块大小的数据时,客户端将链接NameNode。NameNode将文件名插入到文件系统层次结构中,为其分配一个数据块。NameNode使用DataNode和目标数据块的标识响应客户端请求。而后客户端将数据块从本地缓冲区刷新到指定的DataNode。关闭文件时,本地缓冲区中剩余的未刷新数据将传输到DataNode。客户端而后告诉NameNode该文件是关闭的。此时,NameNode将文件建立操做提交到持久存储。若是NameNode在文件关闭以前死机,该文件将丢失。
上述方法在仔细考虑了在HDFS上运行的目标应用程序后才采用。这些应用程序须要流式写入文件。若是客户端直接写入远程文件而没有任何客户端缓冲,网络速度和网络拥塞就会大大影响吞吐量。这种作法并不是没有先例。早期的分布式文件系统,例如AFS使用客户端缓存来提升性能。POSIX要求已放宽,以实现更高性能的数据上传。
当客户端将数据写入HDFS文件时,首先将其数据写入本地缓冲区,如上一节所述。假设HDFS文件的复制因子为3。当本地缓冲区累积一大批用户数据时,客户端将从NameNode中检索一个DataNodes列表。该列表包含将承载该块的副本的DataNodes。而后,客户端将数据块刷新到第一个DataNode。第一个DataNode开始以小部分接收数据,将每一个部分写入其本地存储库,并将该部分传输到列表中的第二个DataNode。第二个DataNode又开始接收数据块的每一个部分,将该部分写入其存储库,而后将该部分刷新到第三个DataNode。最后,第三个DataNode将数据写入本地存储库。所以,DataNode能够在流水线中接收来自前一个数据的数据,而且同时将数据转发到流水线中的下一个数据。所以,数据从一个DataNode流水线到下一个。
HDFS能够从应用程序以许多不一样的方式访问。原本,HDFS提供了一个FileSystem Java API,供应用程序使用。此Java API和REST API的C语言包装器也可用。另外,HTTP浏览器还能够用来浏览HDFS实例的文件。经过使用NFS网关,HDFS能够做为客户端本地文件系统的一部分进行安装。
HDFS容许以文件和目录的形式组织用户数据。它提供了一个名为FS shell的命令行接口,可以让用户与HDFS中的数据进行交互。该命令集的语法相似于用户已经熟悉的其余shell(例如bash,csh)。如下是一些示例操做/命令对:
Action | Command |
---|---|
Create a directory named /foodir | bin/hadoop dfs -mkdir /foodir |
Remove a directory named /foodir | bin/hadoop fs -rm -R /foodir |
View the contents of a file named /foodir/myfile.txt | bin/hadoop dfs -cat /foodir/myfile.txt |
FS shell针对须要使用脚本语言与存储数据进行交互的应用程序。
DFSAdmin命令集用于管理HDFS集群。这些是仅由HDFS管理员使用的命令。如下是一些示例操做/命令对:
Action | Command |
---|---|
Put the cluster in Safemode | bin/hdfs dfsadmin -safemode enter |
Generate a list of DataNodes | bin/hdfs dfsadmin -report |
Recommission or decommission DataNode(s) | bin/hdfs dfsadmin -refreshNodes |
典型的HDFS安装配置Web服务器以经过可配置的TCP端口公开HDFS命名空间。这容许用户浏览HDFS命名空间,并使用Web浏览器查看其文件的内容。
若是启用垃圾箱配置,FS Shell删除的文件不会当即从HDFS中删除。相反,HDFS将其移动到垃圾目录(每一个用户在/user/<username>/.Trash下都有本身的垃圾文件目录)。只要文件保留在垃圾箱中,文件能够快速恢复。
大多数最近删除的文件被移动到当前垃圾桶目录(/user/<username>/.Trash/Current),而且在可配置的时间间隔内,HDFS建立检查点(在/ user / <username> /。垃圾桶/ <date>下)对于当前垃圾目录中的文件,并在旧的检查点过时时删除它们。请参阅FS shell关于检查垃圾的清除命令。
Trash生命周期到期时,Namenode从HDFS命名空间中删除该文件。删除文件会致使与文件关联的块被释放。请注意,在用户删除文件的时间与HDFS中可用空间相应增长的时间之间可能会有明显的时间延迟。
如下是一个示例,显示如何从FS Shell从HDFS中删除文件。咱们建立了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:9820/user/hadoop/delete/test1 to trash at: hdfs://localhost:9820/user/hadoop/.Trash/Current
如今咱们将使用skipTrash选项删除该文件,该选项不会将文件发送到Trash。它将从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 source code: http://hadoop.apache.org/version_control.html