Hadoop分布式文件系统(HDFS)是一种分布式文件系统,设计用于在商品硬件上运行。它与现有的分布式文件系统有许多相似之处。然而,与其他分布式文件系统的区别是显著的。HDFS具有高度容错性,设计用于部署在低成本硬件上。HDFS提供对应用程序数据的高吞吐量访问,适用于具有大型数据集的应用程序。HDFS放宽了一些POSIX要求,以实现对文件系统数据的流式访问。HDFS最初是作为Apache Nutch web搜索引擎项目的基础设施构建的。HDFS是Apache Hadoop核心项目的一部分。项目URL为http://hadoop.apache.org/.
- 容错性
- 硬件成本低
- 高吞吐量
- 不支持低延迟数据访问
- 不适合大量小文件存储–每个文件的元数据信息都会存储在NameNode中,占用150b空间,所以说大文件与小文件在NameNode中的占用空间是相同,存储小文件浪费资源,大量的小文件元数据信息将把NameNode空间占满,无法存储新的文件
- 不支持并发写入,一个文件只有一个写入者
- 不能任意位置修改文件,只能追加
硬件故障是常态,而不是例外。HDFS实例可能由数百或数千台服务器机器组成,每个服务器机器存储文件系统的部分数据。事实上,有大量的组件,每个组件都有非常小的故障概率,这意味着HDFS的某些组件总是不起作用的。因此,故障检测和快速自动恢复是HDFS的核心架构目标。
在HDFS上运行的应用程序需要对其数据集进行流式访问。它们不是通常在通用文件系统上运行的通用应用程序。HDFS更多地是为批处理而设计的,而不是用户的交互使用。重点是数据访问的高吞吐量,而不是数据访问的低延迟(HDFS的缺点)。POSIX提出了许多针对HDFS的应用程序不需要的硬性要求。一些关键领域的POSIX语义已经被用来提高数据吞吐量。
关键词: 高吞吐量:某一时间内写入大量的数据。 低延迟:以毫秒级读写数据。
在HDFS上运行的应用程序具有大型数据集。HDFS中的典型文件大小为GB到TB。因此,HDFS被调整为支持大型文件。它应该提供高聚合数据带宽,并扩展到单个集群中的数百个节点。它应该在单个实例中支持数千万个文件。
HDFS应用程序需要文件的一次写入-多次读取访问模型。文件创建、写入和关闭后,除了追加和截断外,无需更改。支持将内容追加到文件末尾,但不能在任意位置进行更新。这一假设简化了数据一致性问题,并实现了高吞吐量数据访问。MapReduce应用程序或web爬虫应用程序完全适合此模型。
总结:一次写入,多次读取。一旦写入,不能更改,只能追加。
如果应用程序请求的计算在其操作的数据附近执行,则效率会高得多。当数据集的大小非常大时,尤其如此。这将最小化网络拥塞并增加系统的总吞吐量。假设将计算迁移到更接近数据所在的位置,而不是将数据移动到应用程序运行的位置。HDFS为应用程序提供接口,使其更接近数据所在的位置。
HDFS被设计为可从一个平台轻松移植到另一个平台。这有助于广泛采用HDFS作为大型应用程序的选择平台。
HDFS具有主/从架构。HDFS集群由一个NameNode组成,这是一个管理文件系统名称空间并管理客户端对文件的访问的主服务器。此外,还有许多DataNode,通常是集群中的每个节点一个,用于管理连接到它们运行的节点的存储。HDFS公开了文件系统命名空间,并允许用户数据存储在文件中。在内部,文件被分割成一个或多个块,这些块存储在一组DataNode中。NameNode执行文件系统命名空间操作,如打开、关闭和重命名文件和目录。它还确定块到DataNode的映射。DataNode负责处理来自文件系统客户端的读写请求。DataNode还根据NameNode的指令执行块创建、删除和复制。
NameNode和DataNode是设计用于在商品机器上运行的软件。这些机器通常运行GNU/Linux操作系统(OS)。HDFS使用Java语言构建;任何支持Java的机器都可以运行NameNode或DataNode软件。使用高度可移植的Java语言意味着HDFS可以部署在各种机器上。典型的部署有一台只运行NameNode软件的专用计算机。集群中的其他每台机器都运行一个DataNode软件实例。该体系结构并不排除在同一台机器上运行多个DataNode,但在实际部署中很少出现这种情况。
NameNode:
- 看成一个数据中心
- 执行文件系统命名空间,打开、关闭和重命名文件和目录
- 负责管理DataNode,控制DataNode创建、删除、复制文件
- 管理文件系统命名空间及属性
- 存储文件的副本数
- 存储DataNode上的所有块列表
- 周期性的接收DataNode心跳和区块报告,收到心跳意味着DataNode正常,收集到块报告,更新块列表,随时掌控DataNode中的块信息
- 保存了两个核心的数据结构(FsImage 和 EditLog)用来存储元数据信息–下面有详细介绍他们的作用
DataNode:
- 存储数据
- 处理来自客户的的读写请求–首先要经过NameNode同意
- 每个块默认是128M
HDFS支持传统的分层文件组织。用户或应用程序可以创建目录并在这些目录中存储文件。文件系统命名空间层次结构与大多数其他现有文件系统相似;可以创建和删除文件,将文件从一个目录移动到另一个目录,或重命名文件。HDFS支持用户配额和访问权限。HDFS不支持硬链接或软链接。然而,HDFS体系结构并不排除实现这些功能。
虽然HDFS遵循文件系统的命名约定,但一些路径和名称(例如/.reserved和.snapshot)是保留的。透明加密和快照等功能使用保留路径。
NameNode维护文件系统命名空间。对文件系统名称空间或其属性的任何更改都由NameNode记录。应用程序可以指定应由HDFS维护的文件副本的数量。文件的副本数称为该文件的复制因子。此信息由NameNode存储。
HDFS旨在在大型集群中跨机器可靠地存储非常大的文件。它将每个文件存储为一系列块。复制文件块以实现容错。每个文件的块大小和复制因子是可配置的。
文件中除最后一个块外的所有块都是相同的大小,而在添加了对可变长度块的支持以追加和hsync之后,用户可以启动新块,而无需将最后一个填充到配置的块大小。
应用程序可以指定文件副本的数量。复制因子可以在文件创建时指定,以后可以更改。HDFS中的文件只写一次(除了追加和截断),并且在任何时候都只有一个写入器。
NameNode做出关于块复制的所有决定。它周期性地从集群中的每个数据节点接收心跳和区块报告。收到心跳信号意味着DataNode运行正常。Blockreport包含DataNode上所有块的列表。
副本的放置对HDFS的可靠性和性能至关重要。优化副本放置将HDFS与大多数其他分布式文件系统区分开来。这是一个需要大量调整和经验的特性。机架感知副本放置策略的目的是提高数据可靠性、可用性和网络带宽利用率。副本放置策略的当前实现是朝着这个方向迈出的第一步。实施此策略的短期目标是在生产系统上验证它,了解更多有关其行为的信息,并为测试和研究更复杂的策略奠定基础。
大型HDFS实例运行在通常分布在许多机架上的计算机集群上。不同机架中的两个节点之间的通信必须通过交换机。在大多数情况下,同一机架中机器之间的网络带宽大于不同机架中机器间的网络带宽。
对于常见情况,当复制因子为3时,HDFS的放置策略是,如果写入程序位于数据节点上,则将一个副本放置在本地计算机上,否则放置在与写入程序相同的机架中的随机数据节点上;另一个副本放在不同(远程)机架中的节点上,最后一个副本则放置在相同远程机架中的不同节点上。此策略可减少机架间写入流量,从而通常提高写入性能。机架故障的几率远远小于节点故障的几率;此策略不会影响数据可靠性和可用性保证。然而,它不会减少读取数据时使用的总网络带宽,因为一个块只放置在两个唯一的机架中,而不是三个机架中。使用此策略,块的副本不会均匀分布在机架上。两个副本位于一个机架的不同节点上,其余副本位于其他机架之一的节点上。此策略在不影响数据可靠性或读取性能的情况下提高了写入性能。
总结: 复制因子为3时
- 第一个副本放置在本地计算机
- 第二个副本放置在相同机架的其他数据节点
- 第三个副本放置在其他机架的任意节点 优点:减少了机架间写入流量,提高写性能
如果复制因子大于3,则随机确定第四个和后续副本的位置,同时保持每个机架的副本数量上限((副本-1)/机架+2)。由于NameNode不允许DataNode具有同一块的多个副本,因此创建的最大副本数是当时DataNode的总数。
就近原则,如果HDFS集群跨越多个数据中心,则驻留在本地数据中心的副本优于任何远程副本。
启动时,NameNode会进入一种称为安全模式的特殊状态。当NameNode处于安全模式状态时,只接收读请求,不接收写入修改删除等操作,不会复制数据块。NameNode从DataNode接收心跳和块报告消息。Blockreport包含DataNode中活动的数据块列表。每个块具有指定的最小副本数。当数据块的最小副本数已通过NameNode检查时,该数据块被视为安全复制。NameNode检查到安全复制数据块达到了设置的百分比(默认99.9%),在此基础上再等待30秒,NameNode将退出安全模式状态。然后,它确定仍然具有少于指定数量副本的数据块(如果有的话)的列表。然后,NameNode将这些块复制到其他DataNode。
安全模式命令
# 开启安全模式
hdfs dfsadmin -safemode enter
# 查看安全模式
hdfs dfsadmin -safemode get
# 退出安全模式
hdfs dfsadmin -safemode leave
HDFS命名空间由NameNode存储。NameNode使用名为EditLog的事务日志持久地记录文件系统元数据发生的每个更改。例如,在HDFS中创建一个新文件会导致NameNode在EditLog中插入一条记录,表明这一点。同样,更改文件的复制因子会导致将新记录插入到EditLog中。NameNode使用其本地主机OS文件系统中的文件来存储EditLog。整个文件系统名称空间(包括块列表信息,系统文件属性)存储在一个名为FsImage的文件中。FsImage也作为文件存储在NameNode的本地文件系统中。
NameNode在内存中保存整个文件系统命名空间和文件块映射的映像。当NameNode启动或到达检查点触发时(检查点触发阈值可配置),它从磁盘读取FsImage和EditLog,将EditLog中的所有事务应用到FsImage的内存表示,并将此新版本刷新到磁盘上的新FsImage。然后,它可以删除旧的EditLog,创建一个新的EditLog,因为它的事务已应用于持久的FsImage。此过程称为检查点。检查点的目的是通过拍摄文件系统元数据的快照并将其保存到FsImage,确保HDFS具有文件系统元数据一致的视图。尽管读取FsImage很有效,但直接对FsImage进行增量编辑并不有效。我们没有为每次编辑修改FsImage,而是将编辑保存在Editlog中。在检查点期间,Editlog中的更改将应用于FsImage。检查点可以在以秒为单位的给定时间间隔(dfs.namenode.checkpoint.period,默认3600,即1小时)触发,也可以在累积了给定数量的文件系统事务(dfs.namenode.chockpoint.txns,默认1,000,000)后触发。如果设置了这两个属性,则要达到的第一个阈值将触发检查点。
总结:NameNode启动或者触发检查点时,它从磁盘中读入fsImage和editLog,将editLog事物合并到fsImage中,合并成功将最新fsImage刷新到磁盘中,同时删除旧的editLog,创建一个新的editLog。
fsImage:保存了最新的元数据,主要包括数据块映射信息、修改时间、访问时间等等
editLog:NameNode已经启动情况下对HDFS进行的各种更新操作进行记录,HDFS客户端执行所有的写操作都会被记录到editlog中
为什么要机型checkpoints:
如果每次写操作都记录在editLog,那么editLog就会越来越大,NameNode启动时将editLog中的事物都操作一遍,时间会很长,所以需要SecondaryNameNode定期checkpoint将editLog合并到fsimage中
HDFS的主要目标是即使在出现故障时也能可靠地存储数据。三种常见的故障类型是NameNode故障、DataNode故障和网络割裂。
每个DataNode定期向NameNode发送心跳消息。网络分区可能会导致DataNode的子集失去与NameNode的连接。NameNode通过缺少心跳消息来检测此情况。NameNode将没有最近心跳的DataNode标记为已停止,并且不会向其转发任何新的IO请求。已注册到失效DataNode的任何数据对HDFS都不再可用。DataNode死亡可能会导致某些块的复制因子低于其指定值。NameNode不断跟踪需要复制的块,并在必要时启动复制。重新复制的必要性可能有多种原因:DataNode可能不可用,副本可能损坏,DataNode上的硬盘可能出现故障,或者文件的复制系数可能增加。
将DataNodes标记为dead的超时时间保持地很长(默认情况下超过10分钟),以避免DataNodes的状态波动导致的复制风暴。对于性能敏感的工作负载,用户可以设置更短的时间间隔来将DataNode标记为过时节点,并通过配置避免读取和/或写入过时节点。