玩了HDFS已经有好多年了,之前一直都是边学边用,直到现在才真正有时间记录一下学到的知识O(∩_∩)O

1. 引言



HDFS全称是Hadoop Distributed File System,Hadoop分布式文件系统,顾名思义它是一个分布式的文件系统,设计于运行在普通硬件之上。它和现在的分布式文件系统有很多相似点,但是它们的区别也是很明显的。HDFS是高容错的,被设计于运行在廉价的硬件之上。HDFS能提供高吞吐量的数据访问,适合大规模数据集上的应用。HDFS放宽了一部分POSIX的约束,来实现流式读取文件系统的数据。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的,它是Apache Hadoop核心项目的一部分。



2. 假设和目标

2.1 硬件故障



硬件故障是普遍的,而不应是异常情况。一个HDFS系统可以由数百或数千个服务器组成,每一个服务器都存储着部分的文件系统数据。事实上HDFS是由大量的组件组成,每一个组件都很可能出现故障,这意味着HDFS里面总会有些组件是不能正常工作的。因此,故障的检测和快速自动恢复是HDFS的一个核心架构设计目标。



2.2 流式数据访问



运行在HDFS之上的应用必须流式地访问它们的数据集,它们不是运行在一般文件系统的普通应用。HDFS被设计为更适合批量处理而不是被用户交互式使用,它的重点在于高吞吐量的数据访问而不是低延时的数据访问。POSIX的很多硬性需求对于HDFS的应用来说是非必要的,所以为了提高数据吞吐量比率,HDFS放宽了一部分POSIX的约束。



2.3 大数据集



运行在HDFS之上的应用有大量的数据集。在HDFS里面,典型的文件大小是GB到TB的级别,因此,HDFS被设计成支持存储大文件。它应该提供很高的聚合数据带宽、支持在一个集群里面扩展到数百个节点和存储上千万个文件。



2.4 简单一致性模型



HDFS应用对文件的操作需求是一次写入多次读取的访问模式。一个文件一旦被创建、写入和关闭之后,除了追加和截断内容之外,不需要修改。内容的追加是支持的但不能在任意点修改更新文件,这个假设简化了数据一致性的问题并使高吞吐量的数据访问变得可能。一个MapReduce的应用或者网络爬虫应用十分适用于该模型。


2.5 “移动计算比移动数据更经济”



在靠近数据所存储的位置来进行计算会更加有效率,特别是在计算大数据集的时候,这样可以减少网络的拥堵和提高系统的整体吞吐量。这个假设是通常迁移计算到离数据更近的位置比将数据移动到程序运行更近的位置要更有效。HDFS提供了让应用程序将自己移动到离数据存储更近位置的接口。



2.6 异构软硬件平台间的可移植性



HDFS被设计成可以容易地实现平台间的迁移,这将有助于HDFS被广泛地采用为大型应用程序的首选平台。



3. 命名节点NameNode和数据节点DataNodes



HDFS使用主从架构。一个HDFS集群是由一个NameNode和多个DataNode组成,NameNode是一个管理文件系统命名空间和调节客户端访问文件的主服务器,DataNode是管理对应节点的存储,通常是一个服务器部署一个DataNode。内部地,一个文件被分割为一个或多个数据块,这些数据块被存储在不同的DataNode。NameNode用于操作文件系统的命名空间,例如打开、关闭和重命名文件和目录,同时决定了数据块和DataNode的映射关系。DataNode用于处理数据的读写请求,同时执行数据块的创建,删除和来自NameNode的复制指令。



hdfs的整体架构图 hdfs架构原理_hdfs的整体架构图



NameNode和DataNode都是被设计为可运行在普通服务器之上的软件,这些服务器通常都是使用GNU/Linux的操作系统。HDFS是用Java语言构建的,任何支持Java的服务器都可以启动NameNode和DataNode服务。使用高度可移植的Java语言意味着HDFS可以部署在广泛的机器上。一个典型的部署方式是单独启动NameNode在一台服务器,集群的其余每一台服务器都启动一个DataNode。也可以把多个DataNode部署在同一台服务器,但在实际的生产环境是不建议的。



集群使用NameNode来大大简化了系统的架构,它是集群的仲裁者和所有HDFS元数据的存储库。系统采用如此的设计方式使得用户的数据不会流经NameNode。



4. 文件系统命名空间



HDFS支持传统的分层文件组织结构。一个用户或应用可以创建目录并把文件存储在这些目录中。HDFS文件系统的命名空间层次结构与其它大多数现有的文件系统类似; 可以创建和删除文件,把文件从一个目录移到另一个目录,或重命名文件。HDFS支持用户配额和访问权限,但不支持硬链接或软链接。然而,HDFS架构并不排除在将来实现这些功能。



NameNode维护文件系统的命名空间,文件系统命名空间或其属性的任何修改都会被NameNode记录。应用程序可以指定文件的副本数,该数值被称为文件的复制因子,这些信息会由NameNode负责保存。



5. 数据复制



HDFS被设计为用于在大型集群中的服务器之间可靠地存储非常大的文件。它把每一个文件存储为序列的块,这些序列块会被复制用于容错,每个文件的块大小和复制因子是可以配置的。同一文件中除了最后一个块之外,其它块的大小都是相同的,而在DistributedFileSystem.append和HdfsDataOutputStream.hsync方法支持参数flag后,用户可以随时新建一个块而不是默认地往最后一个块添加数据直到配置的块大小上限为止。



应用程序可以指定文件的副本数,复制因子可以在创建文件的时候指定,也可以在创建之后修改。HDFS中的文件是一次写入的(除了追加和截断之外),并且在任何时候都只有一个写操作。NameNode负责块复制的所有决策,它周期地接收集群中每个DataNode的心跳和块报告Blockreport,收到心跳意味着DataNode是正常工作的。一份Blockreport包含该DataNode所有块的列表。



hdfs的整体架构图 hdfs架构原理_服务器_02



5.1 副本存放位置



副本的存放位置是会严重影响HDFS的可靠性和性能,它的优化是HDFS区分于其他分布式文件系统的的特点。HDFS使用机架感知rack-aware副本放置策略,它的意图是提高数据可靠性,可用性和网络带宽的利用率。目前的副本放置策略的实现是朝着这个方向努力的第一步,实现这一策略的短期目标是在生产系统上进行验证,更多地了解其行为,并为对更复杂的策略进行测试和研究奠定基础。



大型HDFS实例通常运行在跨多个机架上的服务器集群。不同机架上的两个节点是通过交换机实现通讯的,在大多数情况下,在同一机架上的服务器网络带宽要优于在不同机架上的服务器网络带宽。



NameNode通过Hadoop机架感知确定每个DataNode所属的机架ID。一个简单但不是最优的策略是将副本放在不同的机架上,这样可以防止当整个机架发生故障时丢失数据,并且在读取数据时可以使用不同机架的带宽。该策略把副本均匀地分布到集群中,使得在组件故障的时候能够容易地实现负载均衡。但是,这种策略会对写性能造成负影响,因为写的时候需要把数据块传输到多个不同的机架。



一般情况下,当副本数设置为3时,HDFS的副本放置策略是将一个副本放在本地节点,第二个副本放在同一机架的不同节点,第三个副本放在不同机架上。该策略减少机架间的写流量,提高了写性能。机架故障的几率远远低于节点的故障,该策略不会影响数据的可靠性和可用性保证。然而,当读数据的时候会减少网络带宽的使用,因为数据块仅存在两个不同的机架,而不是三个。文件的副本不是均匀地分布在不同的机架上,三分之一的副本在同一个节点,三分之二的副本在同一个机架,另外三分之一均匀地分布在其余的机架上。这种策略提高了写性能,而且不会影响数据的可靠性和读性能。



目前,这里描述的默认副本放置策略还处于开发之中。



5.2 副本选择



为了尽量减小全局带宽的消耗和读延时,HDFS会尝试从离请求最近的副本读取数据。如果在同一个机架有请求数据的副本,就直接读取,如果HDFS集群是部署在多个数据中心,那么会优先读取本地数据中心的副本,而不是远程的副本。



5.3 安全模式



在HDFS启动的时候,NameNode会进入一个叫安全模式Safemode的特别状态,在此模式下,数据块还不会被复制。NameNode接收来自DataNodes的心跳和Blockreport信息,一份Blockreport包含该DataNode所有块的列表。每一个块有一个特定的最小复制数,当数据块的最小复制数被NameNode检查后,就认为是复制成功。当达到配置的块复制安全比例时(加上额外的30秒),NameNode就退出安全模式状态。然后,它会检测数据块的列表,把少于指定数量副本的数据块复制到其它的DataNodes。