本文主要是作者自己的学习过程,主要是对原文的翻译及理解,某些地方根据自己的理解,在表述上稍做些改动,以便更易于理解。
官方原文


hdfs与现有的分布式文件系统有许多相似之处。但是,与其他分布式文件系统的区别非常明显。HDFS是高度容错的,设计用于部署在低成本硬件上。HDFS提供对应用程序数据的高吞吐量访问,适用于具有大数据集的应用程序。HDFS放宽了一些POSIX要求,以支持对文件系统数据的流式访问。

硬件故障

首先明确:硬件故障是常态而不是意外。检测到错误并且自动的,快速的恢复是hdfs的核心架构目标

流式数据访问

运行在HDFS上的应用程序需要对其数据集进行流访问。它们不是通常在通用文件系统上运行的通用应用程序。HDFS更多的是为批处理而设计的,而不是用户的交互使用。重点是数据访问的高吞吐量,而不是数据访问的低延迟。POSIX强加了许多针对HDFS的应用程序不需要的硬需求

大数据集

运行在HDFS上的应用程序拥有大型数据集。HDFS中的一个典型文件的大小是gb到tb。因此,HDFS被调优为支持大文件。它应该提供高聚合数据带宽,并可扩展到单个集群中的数百个节点。它应该在一个实例中支持数千万个文件。

简单一致性模型

HDFS应用需要文件的write-once-read-many访问模型。文件一旦被创建,写和关闭操作出了追加和截断,无需修改操作。支持将内容附加到文件末尾,但不能在任意点进行更新。这个假设简化了数据一致性问题,并支持高吞吐量数据访问。MapReduce应用程序或web爬虫应用程序非常适合这个模型。

移动计算比移动数据廉价

如果应用程序请求的计算在其操作的数据附近执行,那么它的效率会高得多。当数据集的大小很大时尤其如此。这将最小化网络拥塞,并提高系统的总体吞吐量。这里的假设是,将计算迁移到离数据更近的地方通常比将数据迁移到应用程序运行的地方要好。HDFS为应用提供接口来移动他们自己以达到离数据所在的位置更近。

跨异构硬件和软件平台的可移植性

HDFS被设计成易于从一个平台移植到另一个平台。这有助于广泛采用HDFS作为一组大型应用程序的首选平台。

NameNode and DataNodes

HDFS有一个主/从架构。HDFS集群由一个NameNode(可选secondary NameNode),NameNode是一个主服务器,它管理文件系统名称空间控制客户机对文件的访问。此外,还有许多datanode,通常是集群中的每个物理节点一个datanode,它们管理附加到它们所运行的物理节点上的存储设备。HDFS对外暴露一个文件系统名称空间,并允许将用户数据存储在文件中。在内部,一个文件被分成一个或多个块,这些块存储在一组DataNode中。NameNode执行namespace operations,如打开、关闭和重命名文件和目录。它还决定块到数据块(blocks)和数据节点(DataNodes)间的映射。DataNodes 负责处理来自文件系统客户端读和写请求。DataNodes还根据来自NameNode的指令执行块的创建、删除和复制
image
集群中单个NameNode的存在极大地简化了系统的体系结构。NameNode是所有HDFS元数据的仲裁器和存储库。系统以这样的方式设计,用户数据本身永远不会流经NameNode。

The File System Namespace

HDFS支持传统的分层文件组织。用户或应用程序可以在这些目录中创建目录并存储文件。文件系统名称空间层次结构与大多数现有文件系统相似;可以创建和删除文件,将文件从一个目录移动到另一个目录,或者重命名文件。HDFS支持用户配额和访问权限。HDFS不支持硬链接或软链接。然而,HDFS体系结构并不排除实现这些特性。
NameNode维护文件系统名称空间。对文件系统名称空间或其属性的任何更改都由NameNode记录。应用程序可以指定HDFS应该维护的文件副本的数量。一个文件的拷贝数称为该文件的复制因子。此信息由NameNode存储。

Data Replication

HDFS的设计目的是在跨机器的大型集群中可靠地存储非常大的文件。它将每个文件存储为一系列块(block)。复制文件的块是为了容错。每个文件都可以配置块大小复制因子

除了最后一个块之外,文件中的所有块大小都相同,而用户可以在appendhsync中添加了对可变长度块的支持之后,启动一个新块,而不需要将最后一个块填充到所配置的块大小。

应用程序可以指定文件的副本数量。复制因子可以在文件创建时指定,稍后可以更改。HDFS中的文件是写一次的(除了追加和截断),并且任何时候只有一个writer。

NameNode做出关于复制块的所有决策。它定期从集群中的每个数据节点接收心跳和块报告。接收到心跳意味着DataNode正常工作。块报告包含DataNode上的所有块的列表。

Replica Placement: The First Baby Steps

副本的位置对HDFS的可靠性和性能至关重要。经过优化的副本位置使HDFS区别于大多数其他分布式文件系统。.....

NameNode通过Hadoop 机架感知中概述的过程确定每个DataNode所属的机架id。一个简单但非最优的策略是将副本放在各个唯一的机架上。这可以防止在某个机架整体发生故障时丢失数据,并允许在读取数据时使用多个机架的带宽。该策略在集群中均匀分布副本,这使得在组件发生故障时很容易平衡负载。但是,这个策略增加了写的成本,因为写需要将块转移到多个机架

为了最小化全局带宽消耗和读取延迟,HDFS尝试满足来自最接近读取器的副本的读取请求。如果在与读取器节点相同的机架上存在一个副本,则首选该副本来满足读取请求。如果HDFS集群跨越多个数据中心,则首选驻留在本地数据中心的副本,而不是任何远程副本。

一般情况下,当复制因子是3时,HDFS的放置策略是:

  1. 将一个副本放在本机如果写入者位于一个datanode上,否则就放置在一个随机的datanode
  2. 另一个副本放置在一个不同的机架上的datanode
  3. 最后一个副本放置在和2相同机架的另一个datanode

这个策略减少了机架间的写流量,这通常可以提高写性能。整个机架失效的概率要远小于某个节点失效的概率,因此该策略并不影响对数据可靠性和可用性的保证。但是,它确减少了读取数据时使用的聚合网络带宽,因为一个块只放在两个而不是三个机架中。使用此策略,文件的副本不会均匀地分布在机架上。三分之一的副本在一个节点上,三分之二的副本在一个机架上,另外三分之一均匀地分布在剩余的机架上。该策略在不影响数据可靠性或读取性能的情况下提高了写性能。

如果复制因子大于3,那么第4个以及后续的副本将随机选择datanode放置,但是每个节点的副本数量有限制(基本上是(replicas - 1) / racks + 2)

因为NameNode不允许数据阳极具有相同块的多个副本,所以创建的最大副本数量是当时的datanode总数。

在向HDFS添加了对Storage Types and Storage Policies的支持之后,除了上面描述的机架感知之外,NameNode还考虑这两种策略。NameNode首先根据机架感知选择节点,然后检查候选节点是否具有与文件关联的策略所需的存储空间。如果候选节点没有存储类型,则NameNode将查找另一个节点。 If enough nodes to place replicas can not be found in the first path, the NameNode looks for nodes having fallback storage types in the second path.

Replica Selection

总体而言就近读
为了最小化全局带宽消耗和读取延迟,HDFS尝试满足来自最接近读取器的副本的读取请求。如果在与读取器节点相同的机架上存在一个副本,则首选该副本来满足读取请求。如果HDFS集群跨越多个数据中心,则首选驻留在本地数据中心的副本,而不是任何远程副本。

Safemode

在启动时,NameNode进入一个称为Safemode的特殊状态。当NameNode处于Safemode状态时,不会发生数据块的复制。NameNode接收来自datanode的心跳和块报告消息。块报告包含DataNode托管的数据块列表。每个块都有指定的最小数量的副本。当NameNode检查到一个数据块已经达到它所指定的最小副本数时就认为该数据块已经安全复制。在达到一个可配置的“已安全复制的数据块”的百分比之后(再加上30秒),NameNode退出Safemode状态。然后,NameNode检查仍然小于指定副本数的数据块列表(如果有的话),并将这些块复制到其他datanode。

The Persistence of File System Metadata

HDFS名称空间由NameNode存储。NameNode使用名为EditLog的事务日志持久地记录文件系统元数据中发生的每个更改。例如,在HDFS中创建一个新文件会导致NameNode将一条记录插入到表明这一点的EditLog中。类似地,更改文件的复制因子会将一条新记录插入EditLog。NameNode使用其本地主机OS文件系统中的一个文件来存储EditLog。整个文件系统名称空间(包括块到文件的映射和文件系统属性)存储在一个名为FsImage的文件中。FsImage也作为文件存储在NameNode的本地文件系统中

NameNode在内存中保存整个文件系统名称空间和文件块映射的镜像。当NameNode启动时,或者一个检查点(checkpoint)被一个可配置的阈值触发时,它从磁盘读取FsImage和EditLog,将EditLog中的所有事务应用于FsImage的内存镜像,并将这个新版本刷新到磁盘上的一个新FsImage中。然后,它可以截断(truncate)旧的EditLog,因为它的事务已应用于持久FsImage。这个过程称为checkpoint。checkpoint的目的是通过获取文件系统元数据快照并将其保存到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

The Communication Protocols

所有HDFS通信协议都位于TCP/IP协议之上。客户端建立链接到NameNode上的可配置TCP端口,它使用ClientProtocol与NameNode通信。DataNode使用DataNode Protocol与NameNode通信。远程过程调用(RPC)抽象封装了Client ProtocolDataNode Protocol。按照设计,NameNode从不启动任何rpc。相反,它只响应由datanode或客户端发出的RPC请求。

Robustness 健壮性

HDFS的主要目标是即使在出现故障时也能可靠地存储数据。常见的三种故障类型是NameNode故障DataNode故障network partitions

Data Disk Failure, Heartbeats and Re-Replication

每个DataNode定期向NameNode发送一条心跳消息。网络分区(network partition)可能导致部分DataNodes与NameNode失去连接。NameNode通过Heartbeat message的缺席来检测这种情况。NameNode将没有心跳的DataNode标记为死节点,并且不向它们转发任何新的IO请求。已注册到死DataNode的任何数据都不再对HDFS可用。DataNode死亡可能导致某些数据块的复制因子低于指定值。NameNode不断跟踪需要复制哪些块,并在必要时启动复制。重新复制的必要性可能由许多原因引起:DataNode可能不可用,副本可能损坏,DataNode上的硬盘可能失败,或者文件的复制因子可能增加

将DataNodes标记为死亡的时限谨慎的设置的比较长(默认超过10分钟),以避免由于DataNode状态抖动而引起的复制风暴。用户可以设置更短的间隔,将datanode标记为陈旧的节点,并避免在配置为性能敏感的工作负载时在陈旧数据节点上读或写(待深入理解 Users can set shorter interval to mark DataNodes as stale and avoid stale nodes on reading and/or writing by configuration for performance sensitive workloads.)

Cluster Rebalancing

HDFS体系结构与数据rebalancing方案兼容。如果DataNode上的空闲空间低于某个阈值,则方案可能会自动将数据从一个DataNode移动到另一个DataNode。In the event of a sudden high demand for a particular file, a scheme might dynamically create additional replicas and rebalance other data in the cluster. These types of data rebalancing schemes are not yet implemented.

Data Integrity

从DataNode获取的数据块可能损坏。这种损坏可能由于存储设备、网络故障或有bug的软件中的错误而发生。HDFS客户端软件实现对HDFS文件内容的校验和检查。当客户端创建HDFS文件时,它计算该文件的每个块的校验和,并将这些校验和存储在相同HDFS名称空间中的一个单独的隐藏文件中。当客户机检索文件内容时,它验证从每个DataNode接收到的数据是否与存储在关联校验和文件中的校验和匹配。如果没有,则客户端可以选择从具有该块副本的另一个DataNode检索该块。

文件快和校验文件
[root@datanode04 ~]# ll -h /data/hadoop/tmp/dfs/data/current/BP-855898234-106.66.38.101-1483934264653/current/finalized//subdir116/subdir82
total 835M
-rw-rw-r-- 1 hadoop hadoop  50M May  3 05:01 blk_1114919483
-rw-rw-r-- 1 hadoop hadoop 393K May  3 05:01 blk_1114919483_41260856.meta
-rw-rw-r-- 1 hadoop hadoop  49M May  3 05:01 blk_1114919485
-rw-rw-r-- 1 hadoop hadoop 392K May  3 05:01 blk_1114919485_41260858.meta
... ...

Metadata Disk Failure

FsImage和EditLog是HDFS的中心数据结构。这些文件的损坏可能导致HDFS实例不可用。因此,可以将NameNode配置为支持维护FsImage和EditLog的多个副本。对FsImage或EditLog的任何更新都会导致同步更新每个FsImage和EditLog。FsImage和EditLog的多个副本的同步更新可能会降低NameNode每秒可以支持的namespace事务的速度。但是,这种损失是可以接受的,因为即使HDFS应用程序本质上是数据密集型的,但它们不是元数据密集型的。当NameNode重新启动时,它选择最新一致的FsImage和EditLog来使用。

提高故障恢复能力的另一个选项是使用多个namenode, shared storage on NFS 或使用distributed edit log (称为Journal)启用高可用性。后者是推荐的方法。

Data Organization

Data Blocks

HDFS被设计成支持非常大的文件。与HDFS兼容的应用程序也是那些处理大数据集的应用程序。这些应用程序只写他们的数据一次,但他们读取它一次或多次,并要求这些读取满足流速度。HDFS支持文件上的write-once-read-many语义。HDFS使用的典型块大小为128mb,因此,HDFS文件被分割成128mb的块,如果可能,每个块将驻留在不同的DataNode上。

Replication Pipelining

当客户机将数据写入复制因子为3的HDFS文件时,NameNode使用“复制目标选择算法”获取目标DataNodes列表。此列表包含将承载该数据块块副本的datanode。然后客户端写入第一个DataNode。第一个DataNode开始接收被切分成块的数据,将每个块写入它的本地存储库(本地文件系统),并将该部分数据传输到列表中的第二个DataNode。然后,第二个DataNode开始接收数据块的每个部分,将该部分写到它的存储库中,然后将该部分刷新到第三个DataNode。最后,第三个DataNode将数据写入其本地存储库。因此,DataNode可以从管道中的前一个接收数据,同时将数据转发到管道中的下一个。因此,数据以pipelilne的形式从一个DataNode传输到下一个DataNode。

Accessibility

可以通过许多不同的方式从应用程序访问HDFS。从本质上讲,HDFS为应用程序提供了一个文件系统Java API。还提供了用于此Java API和REST API的C语言包装器。此外,HTTP浏览器还可以用来浏览HDFS实例的文件。通过使用NFS网关,HDFS可以作为客户机本地文件系统的一部分挂载。

Space Reclamation

File Deletes and Undeletes

,由FS Shell删除的文件不会立即从HDFS中删除。相反,HDFS将其移动到一个垃圾目录(每个用户在/user/<username>/. trash下都有自己的垃圾目录)。只要文件保存在垃圾中,就可以快速恢复。最近删除的文件被移动到当前垃圾目录(/user/<username>/. trash / current),在一个可配置的间隔内,HDFS为当前垃圾目录中的文件创建检查点(在/user/<username>/. trash /<date>下),并在旧检查点过期时删除它们。有关垃圾的检查点,请参阅FS shell的expunge命令。在垃圾中的生命周期结束后,NameNode将从HDFS名称空间中删除该文件。删除文件会释放与文件关联的块。注意,从用户删除文件的时间到HDFS中相应的空闲空间增加的时间之间可能存在明显的时间延迟。

如果开启回收站特性的话,可以通过如下参数强制删除

hadoop fs -rm -r -skipTrash delete/test2

Decrease Replication Factor

当文件的复制因子降低时,NameNode选择可以删除的多余副本。下一个心跳将此信息传输到DataNode。然后,DataNode删除相应的块,集群中出现相应的空闲空间。同样,在完成setReplication API调用和集群中出现空闲空间之间可能存在时间延迟。