Hadoop分布式文件系统(HDFS)
是一种旨在在商品硬件上运行的分布式文件系统
。它与现有的分布式文件系统有许多相似之处
。但是,与其他分布式文件系统的区别很明显
。HDFS具有高度的容错能力
,旨在部署在低成本硬件上
。HDFS提供对应用程序数据的高吞吐量访问
,并且适用于具有大数据集
的应用程序。HDFS放宽了一些POSIX要求,以实现对文件系统数据的流式访问。HDFS最初是作为Apache Nutch Web
搜索引擎项目的基础结构而构建的。HDFS现在是Apache Hadoop子项目。项目URL是https://hadoop.apache.org/hdfs/。
硬件故障是正常现象
,而非例外。HDFS实例可能包含数百或数千个服务器计算机
,每个服务器计算机都存储文件系统数据的一部分
。存在大量组件并且每个组件的故障概率都很低的事实意味着HDFS的某些组件始终无法运行。因此,检测故障并快速
,自动地从故障中恢复是HDFS的核心目标
。
在HDFS上运行的应用程序需要对其数据集进行流式访问
。它们不是通常在通用文件系统上运行的通用应用程序。HDFS设计用于批处理
,而不是用户交互使用。重点在于数据访问的高吞吐量
,而不是数据访问的低延迟。POSIX提出了许多针对HDFS的应用程序不需要的硬性要求
。在一些关键领域中,POSIX语义已经被交易以提高数据吞吐率
。
在HDFS上运行的应用程序具有大量数据集
。HDFS中的典型文件大小为GB到TB
。因此,HDFS已调整为支持大文件
。它应提供较高的聚合数据带宽
,并可以扩展到单个群集中的数百个节点
。它应该在单个实例中支持数千万个文件
。
HDFS应用程序需要文件一次写入多次读取访问模型
。创建
,写入
和关闭
的文件无需更改
。该假设简化了数据一致性问题
并实现了高吞吐量数据访问
。MapReduce
应用程序或Web爬网程序
应用程序非常适合此模型
。有计划在将来支持对文件的追加写入
。
如果应用程序所请求的计算在其所操作的数据附近执行,则效率会高得多。当数据集的大小巨大时,尤其如此。这样可以最大程度地减少网络拥塞
,并提高系统的整体吞吐量
。假设通常是将计算迁移到更靠近数据的位置,而不是将数据移动到应用程序正在运行的位置。HDFS为应用程序提供了接口
,使它们自己更靠近数据所在的位置。
HDFS的设计目的是可以轻松地从一个平台移植到另一个平台
。这有助于将HDFS广泛用作大量应用程序的首选平台。
HDFS具有主/从体系结构
。HDFS群集由单个NameNode和管理文件系统名称空间并控制客户端对文件的访问的主服务器组成
。此外,还有许多数据节点,通常是集群中每个节点一个,用于管理
与它们所运行的节点相连的存储
。HDFS公开了文件系统名称空间
,并允许用户数据存储在文件中。在内部,文件被分成一个或多个块
,这些块存储在一组DataNode中
。NameNode执行文件系统名称空间操作
,例如打开
,关闭
和重命名文件和目录
。它还确定块到DataNode的映射
。数据节点负责处理来自文件系统客户端的读写请求
。
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中的文件只能写入一次,并且在任何时候都只能有一个写入者
。
NameNode做出有关块复制的所有决定
。它定期从群集中的每个DataNode接收心跳信号和Blockreport
。收到心跳信号表示DataNode正常运行
。Blockreport包含DataNode上所有块的列表
。
复制副本的位置对于HDFS的可靠性和性能至关重要
。优化副本放置将HDFS与大多数其他分布式文件系统区分开来。此功能需要大量调整和经验。支持机架的副本放置策略
的目的是提高数据可靠性
,可用性和网络带宽利用率
。副本放置策略
的当前实现是朝这个方向的第一步
。实施此策略的短期目标是在生产系统上对其进行验证,进一步了解其行为,并为测试和研究更复杂的策略奠定基础。
大型HDFS实例
在通常分布在许多机架上的计算机群集上运行
。不同机架中的两个节点之间的通信必须通过交换机进行
。在大多数情况下,同一机架中的计算机之间的网络带宽大于不同机架中的计算机之间的网络带宽
。
NameNode通过Hadoop Rack Awareness
(网址解释)中概述的过程确定每个DataNode所属的机架ID
。一个简单但非最佳的策略是将副本放置在唯一的机架上。这样可以防止在整个机架出现故障时丢失数据
,并允许在读取数据时使用多个机架的带宽
。此策略在群集中平均分配副本
,这使得平衡组件故障时的负载变得容易
。但是,此策略增加了写入成本
,因为写入需要将块传输到多个机架
。
对于常见情况,当复制因子为3时,HDFS的放置策略是将一个副本放置在本地机架中的一个节点上,将另一个副本放置在不同(远程)机架中的一个节点上,最后一个副本放置在同一机架中的另一个节点上远程机架。该策略减少了机架间的写流量
,通常可以提高写性能
。机架故障的机会远小于节点故障的机会。此策略不会影响数据的可靠性和可用性保证
。但是,由于一个块仅放置在两个唯一的机架中,而不是三个
,因此它确实减少了读取数据时使用的总网络带宽
。使用此策略,文件的副本不会在机架上均匀分布
。三分之一的副本位于一个节点上,三分之二的副本位于一个机架上,其余三分之一则平均分布在其余机架上。此策略可提高写入性能,而不会影响数据可靠性或读取性能。
这里描述的当前默认副本放置策略
是一项正在进行的工作。
为了最大程度地减少全局带宽消耗和读取延迟
,HDFS尝试满足最接近读取器的副本的读取请求
。如果在与读取器节点相同的机架上存在一个副本,则首选该副本以满足读取请求。如果angg / HDFS群集跨越多个数据中心
,则驻留在本地数据中心中的副本比任何远程副本都更可取
。
启动时,NameNode进入一个特殊的状态,称为安全模式
。当NameNode处于安全模式状态时,不会发生数据块的复制
。NameNode从数据节点接收心跳和Blockreport消息。Blockreport包含
DataNode托管的数据块列表
。每个块都有指定的最小副本数
。当已使用NameNode检入该数据块的最小副本数时,该块被视为已安全复制
。在可配置百分比的安全复制数据块中通过NameNode签入(再加上30秒)
后,NameNode退出安全模式状态
。然后,它确定仍少于指定数量的副本的数据块列表(如果有)。
HDFS命名空间由NameNode存储
。NameNode使用一个称为EditLog的事务日志
来永久记录文件系统元数据发生的每个更改
。例如,在HDFS中创建一个新文件会导致NameNode将一条记录插入到EditLog中,以表明这一点。同样,更改文件的复制因子会导致将新记录插入到EditLog中。NameNode使用其本地主机OS文件系统中的文件来存储EditLog
。整个文件系统名称空间
(包括块到文件的映射和文件系统属性
)存储在名为FsImage
的文件中。FsImage也作为文件存储在NameNode的本地文件系统中。
NameNode在内存中保留整个文件系统名称空间和文件Blockmap
(索引模式)的图像。此关键元数据项设计得紧凑,因此具有4 GB
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计算
机上可配置TCP
端口的连接。它将ClientProtocol与NameNode进行通信。
DataNode使用DataNode协议与NameNode对话。远程过程调用(RPC)抽象包装了客户端协议和DataNode协议。
按照设计,NameNode永远不会启动任何RPC
。相反,它仅响应
由DataNodes或客户端发出的RPC请求
。
HDFS的主要目标是即使出现故障也能可靠地存储数据
。三种常见的故障类型是NameNode故障
,DataNode故障
和网络分区
。
每个DataNode定期向NameNode发送心跳消息。网络分区可能导致DataNode的子集失去与NameNode的连接
。NameNode通过缺少心跳消息来检测到这种情况。NameNode将没有最近心跳的DataNode标记为已死
,并且不转发任何新IO向他们提出要求
。已注册到失效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和EditLogs中的每个同步更新。
同步更新FsImage和EditLog的多个副本可能会降低NameNode可以支持的每秒名称空间事务处理的速度
。但是,这种降级是可以接受的
,因为即使HDFS应用程序本质上是数据密集型的
,但它们也不是元数据密集型的
。当NameNode重新启动时
,它将选择要使用的最新一致的FsImage和EditLog
。
NameNode计算机是HDFS群集的单点故障
。如果NameNode计算机发生故障,则需要手动干预
。当前,不支持将NameNode软件自动重新启动和故障转移到另一台计算机。
快照支持在特定时间存储数据副本
。快照功能的一种用法可能是将损坏的HDFS实例回滚
到以前已知的良好时间点
。HDFS当前不支持快照
,但在将来的版本中将支持快照。
HDFS旨在支持非常大的文件
。与HDFS兼容的应用程序是处理大型数据集的应用程序。这些应用程序仅写入一次数据,但读取一次或多次,并要求以流速度满足这些读取要求。HDFS支持文件上一次写入多次读取的语义
。HDFS使用的典型块大小为64 MB。因此,HDFS文件被切成64 MB的块,并且如果可能的话,每个块将驻留在不同的DataNode上。Hadoop1.x版本块大小是64MB,Hadoop12.x版本块大小是128MB,Hadoop13.x版本块大小是256MB。
客户端创建文件的请求不会立即到达NameNode。
实际上,最初,HDFS客户端将文件数据缓存到临时本地文件中
。应用程序写入透明地重定向到此临时本地文件
。当本地文件累积的数据超过一个HDFS块大小
时,客户端将联系NameNode。NameNode将文件名插入文件系统层次结构中
,并为其分配数据块
。NameNode以DataNode和目标数据块的身份响应客户端请求
。然后,客户端将数据块从本地临时文件刷新到指定的DataNode
。关闭文件后,临时本地文件中剩余的未刷新数据将传输到DataNode。然后,客户端告诉NameNode该文件已关闭
。此时,NameNode会将文件创建操作提交到持久性存储中。如果NameNode在关闭文件之前死亡,则该文件将丢失。
在仔细考虑了在HDFS上运行的目标应用程序之后,采用了上述方法。这些应用程序需要流式写入文件
。如果客户端在没有任何客户端缓冲的情况下直接写入远程文件
,则网络速度和网络拥塞将严重影响吞吐量
。这种方法并非没有先例。较早的分布式文件系统(例如AFS)已使用客户端缓存来提高性能
。放宽了POSIX要求,以实现更高的数据上传性能
客户端将数据写入HDFS文件时,其数据首先被写入本地文件
,如上一节所述。假设HDFS文件的复制因子为3。当本地文件累积了完整的用户数据块时,客户端将从NameNode检索DataNode列表。该列表包含将托管该块副本的DataNode。然后,客户端将数据块刷新到第一个DataNode。第一个DataNode开始以小部分(4 KB
)的形式接收数据,将每个部分写入其本地存储库,并将该部分传输到列表中的第二个DataNode。第二个DataNode依次开始接收数据块的每个部分,将该部分写入其存储库,然后将该部分刷新到第三个DataNode。最后,第三个DataNode将数据写入其本地存储库。因此,DataNode可以从流水线中的上一个接收数据,同时将数据转发到流水线中的下一个。因此,数据从一个DataNode流到下一个DataNode
可以通过许多不同的方式从应用程序访问HDFS。HDFS本身就为应用程序提供了 Java API。也提供此Java API的AC语言包装器。另外,HTTP浏览器也可用于浏览HDFS实例的文件
。通过WebDAV协议公开HDFS的工作正在进行中。
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命令集用于管理HDFS群集
。这些是仅由HDFS管理员使用的命令。以下是一些示例操作/命令对:
将群集置于安全模式 |
bin / hadoop dfsadmin -safemodeenter |
---|---|
生成数据节点列表 |
bin / hadoop dfsadmin-report |
重新启用或停用DataNode |
bin / hadoop dfsadmin -refreshNodes |
典型的HDFS安装会将Web服务器配置为通过可配置的TCP端口公开HDFS命名空间
。这允许用户使用Web浏览器浏览HDFS命名空间并查看其文件的内容。
用户或应用程序删除文件后,不会立即将其从HDFS中删除
。相反,HDFS首先将其重命名为/ trash目录中的文件
。只要文件保留在/ trash中,就可以快速恢复该文件。文件在/ trash中保留可配置的时间。
在/ trash中到期后,NameNode将从HDFS命名空间中删除该文件。文件的删除导致与文件关联的块被释放。请注意,在用户删除文件的时间与HDFS中相应的可用空间增加的时间之间,可能会有明显的时间延迟。
只要文件保留在/ trash目录中,用户就可以在删除文件后取消删除该文件。
如果用户要取消删除已删除的文件,则可以浏览/ trash 目录并检索该文件。该/trash 目录仅包含已删除文件的最新副本
。该/trash 目录就像是一个特殊的功能,任何其他目录:HDFS应用于指定的策略从这个目录中自动删除文件。当前的默认策略是从/ trash中删除超过6小时
的文件。将来,可以通过定义明确的界面来配置此策略。
当减少文件的复制因子时,NameNode选择可以删除的多余副本。下一个心跳将此信息传输到DataNode。
然后,DataNode删除相应的块,
并且相应的可用空间出现在群集中。同样,在setReplication API调用完成与群集中的可用空间出现之间可能会有时间延迟
。
后面我会持续更新
,喜欢的小伙伴可以关注
或者`点赞评论哟…
但行好事,莫问前程
,我们下篇见哟。