所涉及到的相关简写如下:

  • NN: NameNode、命名节点
  • DN: DataNode、数据节点
  • RM: ResourceManager
  • NM: NodeManager
  • SNN: Secondary NameNode、第二名称节点
  • QJM: Quorum Journal Manager、群体日志管理器
  • FC: Failover Controller、故障转移控制器
  • ZKFC: Zookeeper Failover Controller、Zookeeper故障转移控制器

一. HDFS是什么

英文全名为Hadoop Distributed File System,中文译为Hadoop分布式文件系统。从名字中就可以知道,其主要职责是存储文件。HDFS是Hadoop的核心组件之一,其是Hadoop的旗舰级操作系统。

二. HDFS的设计概念

HDFS被设计为运行在商用硬件(即普通商店能买到的硬件,但不同于普通PC硬件)之上,其具有如下特点:

  • 存储超大文件:“超大文件”指具有几百MB、几百GB甚至更大文件,其被设计成可以存储超大文件。
  • 运行于商用硬件:其被设计运行于商用硬件之上。商用硬件意味着较高的故障率,当遇到故障时,HDFS被设计成能够继续运行且不会感觉到明显中断。
  • 不支持低延时数据访问:HDFS具有高吞吐量设计,但这是以牺牲时间延迟为代价,低延时是指要求时延在几十毫秒范围内。
  • 小量的大文件优于大量的小文件。此处的小文件是指小于HDFS一个块的文件。HDFS将整个文件系统的元数据(即目录结构,索引等)存储于NameNode的内存中,因此HDFS存储文件的数目取决于NameNode的内存大小。由于HDFS的设计理念,一个小文件也会单独占用一个快,导致资源利用效率降低。
  • 不支持多用于写入,不支持任意修改。HDFS的设计理念为“一次写入,处处使用”,其文件只支持单个写入者,并且不支持在任意位置修改。

三. HDFS基本架构图

hdfs设置文件777 hdfs文件名_hdfs


上图描述了HDFS的基本架构,以下会对相关的知识进行总结.

四. HDFS中的基本概念

1. 数据块

1.1 什么是数据块

数据块(Block)并不是一个陌生的概念,在我们的操作系统中,也存在数据块的概念。数据块是磁盘进行数据读写的最小单位,文件系统构建于数据块之上,用于管理磁盘中的文件。文件系统块一般是磁盘块大小的整数倍。与通常的磁盘文件系统不同的是:HDFS中小于一个块大小的文件不会占据整个块的空间(当一个1MB的文件存储在一个128MB的块中时,文件只使用1MB的磁盘空间,而不是128MB)

1.2 数据块的大小

在HDFS中,一个数据块的大小为128MB(磁盘块一般为512B),相对于磁盘块来说很大,这样做的好处是便于寻址,减少了寻址时间。

  • 为什么HDFS的数据块大小不能小于64M
    因为HDFS文件系统的元数据存放于NameNode内存中,如果块太小,便会造成块数量增多,从而过多消耗NameNode的内存。这也是HDFS不适合存放大量小文件的原因。
  • 为什么HDFS的数据块大小不能远大于64M
  • Map崩溃问题。系统需要重新启动,启动过程中需要重新加载数据,数据块越大,数据加载时间越长,系统恢复过程越长
  • 监管时间问题。主节点监管其他节点的情况,每个节点会周期性的与主节点进行汇报通信。倘若某一个节点保持沉默的时间超过一个预设的时间间隔,主节点会记录这个节点状态为死亡,并将该节点的数据转发给别的节点。而这个“预设时间间隔”是从数据块的角度大致估算的。(加入对64MB的数据块,我可以假设你10分钟之内无论如何也能解决完了吧,超过10分钟还没反应,那我就认为你出故障或已经死了。)64MB大小的数据块,其时间尚可较为精准地估计,如果我将数据块大小设为640MB甚至上G,那这个“预设的时间间隔”便不好估算,估长估短对系统都会造成不必要的损失和资源浪费。
  • 问题分解问题。数据量的大小与问题解决的复杂度呈线性关系。对于同一个算法,处理的数据量越大,时间复杂度越高。
  • 约束Map输出。在Map Reduce框架里,Map之后的数据是要经过排序才执行Reduce操作()的。这通常涉及到归并排序,而归并排序的算法思想便是“对小文件进行排序,然后将小文件归并成大文件”,因此“小文件”不宜过大。
  • 并行运算约束。一般情况下,一个数据块对应一个map,如果数据块过大会造成并行数量较少,影响计算效率。
1.3 使用数据块进行存储的好处
  • 一个文件的所有块不必存储于一台机器上,因此,对于HDFS来说,一个文件的大小可以超过任意一个磁盘的容量。
  • 分离元数据与数据管理,简化存储设计。
  • 利用数据块可以很方便的进行数据备份,提高集群的数据容错能力及可用性。一个很简单的方式就是可以将一个文件的数据块存放在不同的物理主机上,这样即使一台机器宕机,也保证数据不会丢失。
2. 数据块相关操作
-move: 移动损坏的文件到/lost+found目录下 
-delete: 删除损坏的文件 
-openforwrite: 输出检测中的正在被写的文件 
-list-corruptfileblocks: 输出损坏的块及其所属的文件 
-files: 输出正在被检测的文件 
-blocks: 输出block的详细报告 (需要和-files参数一起使用) 
-locations: 输出block的位置信息 (需要和-files参数一起使用) 
-racks: 输出文件块位置所在的机架信息(需要和-files参数一起使用)

例如hdfs fsck /zpy/bigdata/ncdc/simple.txt -files -blocks -racks命令执行结果为:

hdfs设置文件777 hdfs文件名_hdfs设置文件777_02

  • 查询指定文件的状态信息
    在HDFS中,我们可以通过hadoop fs -stat [format] <path>来查询一个文件的相关信息。format的几个重要符号如下:
%b:文件实际大小(单位:字节)
 %o:数据块大小(单位:字节)
  %r:副本个数
  %n:文件名
  %f:文件类型

例如运行hadoop fs -stat 'name: %n---type: %F---real_size: %b----block_size: %o---replicated_num: %r' /zpy/bigdata/ncdc/simple.txt输出如下:

hdfs设置文件777 hdfs文件名_数据块_03

  • 设置数据块大小
    当我们需要自定义HDFS数据块大小的时候,我们可以通过修改hdfs-site.xml文件。修改仅对之后上传的文件生效,对之前的文件不生效。修改完成之后需要重启HDFS集群。
<property>  
	<name>dfs.blocksize</name>  
	<value>30m</value>  
</property>  
<property>  
	<name>dfs.namenode.fs-limits.min-block-size</name>  
	<value>30m</value>  
</property>

2. NameNode与DataNode

HDFS的工作模式为管理节点-工作节点模式,即一个NameNode和多个DataNode

NameNode和DataNode的主要功能分别如下:

  • NameNode:简称NN。负责维护整个文件系统得到系统树即整棵树内的所有目录和文件。这些信息会被以命名空间镜像文件(fsimage_开头的文件)和编辑日志文件(edits_开头的文件)形式永久保存在本地磁盘(dfs.namenode.name.dir定义)上。1
  • DataNode:简称DN。文件系统的工作节点、他们负责根据需要存储并检索数据块,并定时向NN发送他们所存储的块的列表。

3. 块缓存

通常情况下,DN会在磁盘中读取块。但是对于访问频繁的块,DN会将对应的块缓存到DN内存中。默认情况下,一个块仅仅会被缓存到一个DN的内存中,通过堆外块缓存(off-heap block cache)技术实现。

4. HDFS的横向扩展–联邦HDFS

namenode会在内存中保存元数据,这也是HDFS的瓶颈----无法存储大量文件。在HDFS2.X中引入了联邦HDFS来实现横向扩展。此时每个namenode仅需管理命名空间的一部分,比如一个namenode管理/usr目录下文件,另一个管理/share目录下文件。
每个namenode维护一个命名空间卷,由命名空间的元数据和一个数据块池(block pool)组成。数据块池包含该命名空间下文件的所有数据块。
命名空间之间是互相独立的,两两之间不互相通信,因此DN需要注册所有NN,并且每个NN都存储着来自多个数据块池中的数据块。

5. HDFS元数据的备份与存储

HDFS的元数据皆保存在namenode指定的磁盘中,若该文件丢失,也就意味着整个HDFS的文件都丢失了,因此我们可以使用如下两种方式保证文件安全。

  • 将元数据写入磁盘的同时再写入到一个远程挂载的NFS网络文件系统
  • 运行一个辅助namenode(Secondary NameNode,第二名称节点, 简称SNN),其基本处理逻辑是定期拉取并合并namenode的日志文件和命名镜像空间,然后保存合并后的副本并推送给主namenode。

6. HDFS的高可用实现

高可用需要解决的问题是单点失效问题,即单台namenode失效带来的Hadoop服务不可用。挂载NFS(冷启动方式)和第二名称节点的机制并不能解决该问题。前者启动十分耗时,而对于第二名称节点来说,因为机制问题,其元数据总是滞后于实际最新元数据(第二名称节点相当于主namenode的备份机)。

当单节点故障时,为了恢复服务,我们通常需要启动一个拥有文件系统元数据副本的新的namenode(俗称冷启动),通常过程包括:将镜像文件导入内存、重演编辑文件、接收足够多的DN数据块报告然后退出安全模式(安全模式期间NN可读不可写)。对于一个拥有大量文件、大规模的集群来说,NN的启动通常十分耗时。

在hadoop2.0中,使用了active-standby机制实现了集群的高可用。保证当活动NN停止活动后,备用NN后会较快的接管服务。该机制主要解决了高可用所面对的如下问题:

  • 如何保证namenode之间的数据同步问题
  • 如何保证nanenode日志数据和镜像数据的高可用
  • 如何进行namenode之间的故障切换
  • 如何确保namenode是否真的已经停止运行
    以下分别针对以上几个个问题进行解释:
6.1 数据同步与数据高可用

要保证数据高可用,有如下两种解决方式:使用NFS和QJM(群体日志管理器)。Hadoop使用后者。QJM使用一组日志节点形式运行,每一次编辑必须写入到多数节点,从而保证数据不丢失和数据的高可用。

DataNode发送心跳包时会同时向两个NN发送心跳包,从而保证两个NN的数据同步。

6.2 故障切换

系统中有一个故障转移控制器(failover controller, FC),管理活动NN向备用NN切换的过程。默认情况下会使用Zookeeper的故障转移控制器(ZKFC)来保证仅有一个活动NN。

6.3 确认是否已经停止运行

确认原有NN是否已经停止运行的过程称为“规避”。我们使用NFS存储元数据时,其无法保证同一时间只有一个NN写入数据,而QJM可以实现。常用的规避手段包含关闭原NN节点电源等。


  1. 在文件系统执行写操作时,会先将事务记录到编辑日志中。同时namenode在内存中维护文件系统元数据,当编辑日志被修改时,元信息也会被同步更新。