HDFS-概念

1. 简介

HDFS:Hadoop分布式文件系统,主要用来解决海量数据的存储问题,通过统一的命名空间——目录树来定位文件。

在现代的企业环境中,单机容量往往无法存储大量数据,需要跨机器存储。统一管理分布在集群上的文件系统称为分布式文件系统。而一旦在系统中,引入网络,就不可避免地引入了所有网络编程的复杂性,例如挑战之一是如何保证在节点不可用的时候数据不丢失。

传统的网络文件系统(NFS)虽然也称为分布式文件系统,但是其存在一些限制。由于NFS中,文件是存储在单机上,因此无法提供可靠性保证,当很多客户端同时访问NFS Server时,很容易造成服务器压力,造成性能瓶颈。另外如果要对NFS中的文件进行操作,需要首先同步到本地,这些修改在同步到服务端之前,其他客户端是不可见的。某种程度上,NFS不是一种典型的分布式系统,虽然它的文件的确放在远端(单一)的服务器上面。如图所示。

从NFS的协议栈可以看到,它事实上是一种VFS(操作系统对文件的一种抽象)实现。

HDFS的文件分布在集群机器上,同时提供副本进行容错及可靠性保证。例如客户端写入读取文件的直接操作都是分布在集群各个机器上的,没有单点性能压力。

2. 概述

2.1 设计目标

  • 存储大文件:几百M、G、或者TB级别。实际应用中已有很多集群存储的数据达到PB级别。能够处理百万规模以上的文件数量,数量相当之大。
  • 流式数据访问方式: HDFS基于这样的一个假设:最有效的数据处理模式是一次写入、多次读取数据集。经常从数据源生成或者拷贝一次,然后在其上做很多分析工作 。分析工作经常读取其中的大部分数据,即使不是全部。 因此读取整个数据集所需时间比读取第一条记录的延时更重要能够保证数据的一致性
  • 运行于商业硬件上:Hadoop不需要特别贵的、reliable的(可靠的)机器,可运行于普通商用机器。在集群中(尤其是大的集群),节点失败率比较高的HDFS的目标是确保集群在节点失败的时候不会让用户感觉到明显的中断。通过多副本机制提供高可靠性;提供了容错和恢复机制。
  • 高容错性):数据自动保存多个副本;某一个副本丢失以后,它可以自动恢复,这是由 HDFS 内部机制实现的,我们不必关心 。

2.2 HDFS不适用的情况

如下栗子:

  • 低延时的数据访问:对延时要求在毫秒级别的应用,不适合采用HDFS。HDFS是为高吞吐数据传输设计的,因此可能牺牲延时,HBase更适合低延时的数据访问。
  • 大量小文件:文件的元数据(如目录结构,文件block的节点列表,block-node mapping)保存在NameNode的内存中, 整个文件系统的文件数量会受限于NameNode的内存大小。小文件存储的寻道时间会超过读取时间。
    •  经验而言,一个文件/目录/文件块一般占有150字节的元数据内存空间。如果有100万个文件,每个文件占用1个文件块,则需要大约300M的内存。因此十亿级别的文件数量在现有商用机器上难以支持。
  • 多方读写,需要任意的文件修改:HDFS采用追加(append-only)的方式写入数据。不支持文件任意offset的修改。不支持多个写入器(writer)。

2.3 HDFS结构图

1、构成

一个HDFS集群以Master - Worker的模式运行,主要有两种类型的节点:一个NameNode节点和若干的DataNode节点。

2、Block

物理磁盘中有块的概念,磁盘的物理Block是磁盘操作最小的单元,读写操作均以Block为最小单元,一般为512 Byte。

文件系统在物理Block之上抽象了另一层概念,文件系统Block是物理磁盘Block的整数倍。通常为几KB。Hadoop提供的df、fsck这类运维工具都是在文件系统的Block级别上进行操作。

HDFS的Block块比一般单机文件系统大得多,hadoop2.x默认为128M。HDFS的文件被拆分成block-sized的chunk,chunk作为独立单元存储。比Block小的文件不会占用整个Block,只会占据实际大小。例如, 如果一个文件大小为1M,则在HDFS中只会占用1M的空间,而不是128M。

Block Caching(缓存)?

DataNode通常直接从磁盘读取数据,但是频繁使用的Block可以在内存中缓存。默认情况下,一个Block只有一个数据节点会缓存。但是可以针对每个文件可以个性化配置。 
作业调度器(如MapReduce、Spark或者其他框架)可以利用缓存提升性能,例如MapReduce可以把任务运行在有Block缓存的节点上。 
用户或者应用可以向NameNode发送缓存指令(缓存哪个文件,缓存多久), 缓存池的概念用于管理一组缓存的权限和资源。

更多

HDFS的Block为什么这么大? 

一是为了最小化查找(seek)时间,控制定位文件与传输文件所用的时间比例。假设定位到Block所需的时间为10ms,磁盘传输速度为100M/s。如果要将定位到Block所用时间占传输时间的比例控制1%,则Block大小需要约100M。 
但是如果Block设置过大,在MapReduce任务中,Map或者Reduce任务的个数如果小于集群机器数量,会使得作业运行效率很低。

二是为了降低内存消耗,如果块设置的比较小,就需要记录更多块的元数据信息,占用更多内存;如果块设置的较大,也不太好,通常,MapReduce中的任务一次只处理一个块中数据,如果块较大,则会导致任务数较少,可能会造成作业分配不均匀,影响作业的运行速度。

HDFS的Block的大小如何设置?

通常要根据数据量、节点数等因素综合考虑了。

Block抽象的好处?
  • Block的拆分使得单个文件大小可以大于整个磁盘的容量,构成文件的Block可以分布在整个集群中, 理论上,单个文件可以占据集群中所有机器的磁盘。 
  • 使用Block作为存储单元,简化了存储系统(存储系统包括:磁盘、磁盘控制器、存储网络、磁盘阵列、卷管理层、目录虚拟层),对于Block,简化了存储的管理(对于一个磁盘来说,因为Block的大小是固定的,可以很容易的计算出它能存储多少),并且消除了元数据的问题(因为存储的是数据的Block,文件元数据如权限等信息不需要存储,而是由其它系统来单独处理元数据信息)。
  • Block作为容错和高可用机制中的副本单元,即以Block为单位进行复制。

3、NameNode:存放文件系统树(目录树)及所有文件、目录的元数据。

NameNode节点负责客户端请求的响应和元数据的管理(查询、修改,管理文件系统的命名空间,维护文件系统树盒树中所有文件和目录的元数据信息),元数据信息被持久化存储在本地磁盘上。

元数据存储形式:

  • 内存元数据(NameSystem):内存中有一份完整的元数据(内存meta data)
  • 磁盘元数据镜像(FsImage):用于维护文件系统树以及文件树中所有的文件盒文件夹的元数据;磁盘有一个“准完整”的元数据镜像(fsimage)文件(在namenode的工作目录中)
  • 编辑日志(edit log)记录了所有针对文件的创建、删除、重命名等操作;用于衔接内存metadata和持久化元数据镜像fsimage之间的操作日志,可通过日志运算出元数据;

当客户端对hdfs中的文件进行新增或者修改操作,操作记录首先被记入edits log文件中,当客户端操作成功后,相应的元数据会更新到内存meta.data中。

为啥会分为fsimage和edit log呢?

主要是因为fsimage这个文件会很大的,多了之后就不好操作了,就拆分成两个。把后续增量的修改放到EditLog中, 一个FsImage和一个Editlog 进行合并会得到一个新的FsImage。

持久化数据中不包括Block所在的节点列表,及文件的Block分布在集群中的哪些节点上,这些信息是在系统重启的时候重新构建(通过DataNode汇报的Block信息)。

NameNode的容错机制

在HDFS中,NameNode可能成为集群的单点故障,NameNode不可用时,整个文件系统是不可用的。HDFS针对单点故障提供了2种解决机制:

1)备份持久化元数据 

将文件系统的元数据同时写到多个文件系统, 例如同时将元数据写到本地文件系统及NFS。这些备份操作都是同步的、原子的。比较常见的配置是在将持久化状态写到本地硬盘的同时,也写入到一个远程挂载的网络文件系统。

2)Secondary Namenode 

事实上Secondary Namenode并不能被用作Namenode。

Secondary节点定期合并主Namenode的namespace image和edit log, 避免edit log过大,通过创建检查点checkpoint来合并。它会维护一个合并后的namespace image副本, 可用于在Namenode完全崩溃时恢复数据。

Secondary Namenode通常运行在另一台机器上,因为合并操作需要耗费大量的CPU时间以及和NameNode相当的内存。其数据落后于Namenode,因此当Namenode完全崩溃时,会出现数据丢失。 通常做法是拷贝NFS中的备份元数据到Second,将其作为新的主Namenode。 
在HA(High Availability高可用性)中可以运行一个Hot Standby,作为热备份,在Active Namenode故障之后,替代原有Namenode成为Active Namenode。

NameNode结构图

Secondary Namenode的工作过程

  1. SecondaryNameNode会定期和NameNode通信,请求其停止使用EditLog文件,暂时将新的写操作写到一个新的文件edit.new上来,这个操作是瞬间完成,上层写日志的函数完全感觉不到差别; 

  2.  SecondaryNameNode通过HTTP GET方式从NameNode上获取到FsImage和EditLog文件,并下载到本地的相应目录下; 

  3.  SecondaryNameNode将下载下来的FsImage载入到内存,然后一条一条地执行EditLog文件中的各项更新操作,使得内存中的FsImage保持最新;这个过程就是EditLog和FsImage文件合并; 

  4. SecondaryNameNode执行完(3)操作之后,会通过post方式将新的FsImage文件发送到NameNode节点上;

  5. NameNode将从SecondaryNameNode接收到的新的FsImage替换旧的FsImage文件,同时将edit.new替换EditLog文件,通过这个过程EditLog就变小了;

    除了这个自带的备份操作,还需要进行人工的备份,把一份fsimage到多个地方进行备份,万一namenode的节点坏了呢。

4、DataNode

DataNode是文件系统的工作节点,负责存储和提取Block,读写请求可能来自NameNode,也可能直接来自客户端。DataNode周期性向Namenode汇报自己节点上所存储的Block相关信息。(每隔3s发送一个心跳 ,是否存活;每隔10次心跳发送一次blockReport),DataNode存储在本地磁盘上。

5、备份解释

热备份:b是a的热备份,如果a坏掉。那么b马上运行代替a的工作。 
冷备份:b是a的冷备份,如果a坏掉。那么b不能马上代替a工作。但是b上存储a的一些信息,减少a坏掉之后的损失。

3. HDFS Federation

NameNode的内存会制约文件数量。在2.X版本中,HDFS Federation(HDFS联盟)提供了一种横向扩展NameNode的方式。在Federation模式中,每个NameNode管理命名空间的一部分,例如一个NameNode管理/user目录下的文件, 另一个NameNode管理/share目录下的文件。 


每个NameNode管理一个命名空间卷(namespace volumn),所有volumn构成文件系统的元数据。每个NameNode同时维护一个Block Pool,保存Block的节点映射等信息(一个Block Pool由属于同一个namespace的数据块组成。)。各NameNode之间是独立的,每个NameNode节点之间不相互通信,一个节点的失败不会导致其他节点管理的文件不可用。 所有的DataNode节点都需要向集群中的所有NameNode节点注册,并定期的向所有的NameNode节点发送其存储块的报告,并执行来自所有NameNode节点的命令。
客户端使用mount table将文件路径映射到NameNode。mount table是在Namenode群组之上封装了一层,这一层也是一个Hadoop文件系统的实现,通过viewfs:协议访问。?

Federation的优点:

1、扩展性和隔离性

支持多个NameNode水平扩展整个文件系统的namespace,可按照应用程序的用户和种类分离namespace volume,进而增强了数据的隔离性。

2、通用存储服务
Block Pool抽象层为HDFS的架构开启了创新之门。分离block storage layer使得:
a、 新的文件系统(non-HDFS)可以在block storage上构建
b、 新的应用程序(如HBase)可以直接使用block storage层
c、 分离的block storage层为将来完全分布式namespace打下基础

Federation的缺点:

实际上,HDFS Federation并没有完全解决单点故障的问题,虽然NameNode存在多个,但从单个NameNode节点看,仍存在单点故障的问题,如果某个NameNode节点挂掉了,则其管理的文件便不可以访问。

更多

4. HDFS HA(High Availability高可用性)

如上述,在多个文件系统中备份NameNode节点的元数据和使用Secondary NameNode节点以检查点的方式来防止数据丢失,但是这并没有提供高可用的文件系统,NameNode节点仍存在单点故障的问题(single point of failure),如果NameNode节点挂掉,所有的客户端(包括MapReduce任务)将不能读写文件,因为NameNode节点是唯一存储文件元数据和文件到块映射的仓库。在这种情况下,Hadoop将暂停服务直到有新的NameNode节点可用。

从出现故障的节点中恢复,管理员需要使用一个文件系统元数据的副本和DataNode节点的配置信息来启动一个新的NameNode,并让客户端使用这个新的NameNode。新的NameNode节点并不能及时提供服务,直到(i)其命名空间的镜像文件加载到内存(ii)重做编辑日志(iii)获得来自DataNode节点的块报告,才能脱离安全模式,提供服务。在一个含有大量文件和块的大集群中,启动一个新的NameNode节点,至少要30分钟,甚至更多。

为解决这种问题,从Hadoop 2.0版本开始,提供了HDFS  高可用(high availability)的实现,该实现提供一对NameNode节点,其中一个作为活动(active)节点,另一个作为备用节点,一旦活动节点出现故障,备用节点可以很快的接管,继续为客户端提供服务,这期间没有明显的中断现象。

High Avaliability 具体实现方式为:

  • NameNode节点之间必须共享存储、共享编辑日志。当一个备用的NameNode节点启动完毕,它会读取标记日志文件,保持与active NameNode节点状态的同步,然后继续读取由active NameNode节点写入编辑日志文件中的新的状态。
  • DataNode节点必须向两个NameNode节点发送块报告,因为块的映射存储在DataNode节点的内存中,而不是磁盘上。
  • 客户端必须配置处理NameNode节点故障切换的机制,这对用户来说是透明的。
  • Secondary NameNode扮演备用节点的角色,它需要设置检查点,定期检查active NameNode节点的命名空间。

对于高可用的共享存储,有两个选择:一个是使用NFS文件服务器,另一个是仲裁日志管理器(QJM:quorum journal manager)。而HDFS的实现使用的是QJM,主要是为了提供高可用的编辑日志,并且使用QJM也是大多数HDFS推荐的。QJM运行一组日志节点(journal nodes),每一个编辑操作都会被记录到多个日志节点中,通常是3个日志节点,所以系统可以容忍部分日志的丢失。

如果NameNode节点关掉,备用的NameNode节点可以很快的接管(几十秒),因为在备用NameNode节点的内存存储着最新的状态:最新的编辑日志和最新的块映射信息。但是,在实际的观察中,NameNode节点之间的切换时间会较长些(在一分钟左右),因为系统需要确认NameNode节点是否已经失效。

不太可能的情况是,在active NameNode节点挂掉时候,备用的NameNode节点也挂掉了,对于这种情况,管理员仍然可以重新启动备用的NameNode节点,这要比没有高可用的环境好些。

5.Failover and fencing(故障切换和栅栏)

NameNode节点之间的故障切换,是由一个failover controller(故障切换控制器)控制的,它有多种控制器,默认实现为使用的Zookeeper来保证仅有一个活动的NameNode节点。每个NameNode节点都有一个轻量级的故障切换控制器进程,来监控其所在NameNode节点的故障(使用简单的心跳机制),并触发故障切换操作。

在日常的维护中,管理员可以有序的手动启动故障切换,这被称作优雅的故障切换(graceful failover),当然也有不雅的故障切换(ungraceful failover),例如,由于网络慢或网络故障引发的故障切换,即使之前的active NameNode节点仍正在运行。为应对这种情况,HA提供了一种“栅栏”(fencing)的实现方式,来尽力阻止之前活动的NameNode节点做任何破坏的操作。

在同一时间,QJM只允许一个NameNode节点操作编辑日志,然而,也存在一种可能,就是之前的active NameNode节点还在处理来自客户端的读取请求。所以,创建一个栅栏(fence)命令可以中断NameNode节点的进程,废除对共享存储目录的访问,此外,它还可以通过远程管理命令来关闭它的网络端口,关闭节点、甚至强行断电。

如果使用NFS文件服务器来共享编辑日志,那就必须要要使用栅栏,因为NFS文件服务器不能做到在同一时间只允许一个NameNode节点来操作编辑日志文件。?

6.【总结】HDFS保证高可靠的措施

1)冗余备份 

每个文件存储成一系列数据块(Block)。为了容错,文件的所有数据块都会有副本(副本数量即复制因子,课配置)(dfs.replication) 
2)副本存放 
采用机架感知(Rak-aware)的策略来改进数据的可靠性、高可用和网络带宽的利用率 
3)心跳检测 
NameNode周期性地从集群中的每一个DataNode接受心跳包和块报告,收到心跳包说明该DataNode工作正常 
4)安全模式 
系统启动时,NameNode会进入一个安全模式。此时不会出现数据块的写操作。 
5)数据完整性检测 
HDFS客户端软件实现了对HDFS文件内容的校验和(Checksum)检查(dfs.bytes-per-checksum)

6)回收站

HDFS中删除的文件先会保存到一个文件夹中(/trash),方便数据的恢复。当删除的时间超过设置的时间阀后(默认6小时),HDFS会将数据块彻底删除。

7)文件系统镜像和编辑日志

这两种数据是HDFS中的核心数据结构。

8)快照

???

7.【注】Hadoop的HA方案

文件完整性
  • CRC32校验
  • 用其他副本取代损坏文件
Heartbeat
  • Datanode 定期向Namenode发heartbeat 
  • datanode会定期向namenode发送心跳,namenode会指定datanode的状态,如果在指定时间内没收到datanode心跳,namenode就会认为datanode已死亡,将其标记为死亡,然后把存储在这个死亡datanode上的数据块在其他节点上进行重构。始终保证每个数据块的副本数为3或者是设置的副本数。
元数据信息
  • FSImage(文件系统镜像)、Editlog(操作日志)
  • 多份存储
  • 主备NameNode实时切换

 

采用HA的HDFS集群配置两个NameNode,分别处于Active和Standby状态。当Active NameNode故障之后,Standby接过责任继续提供服务,用户没有明显的中断感觉。一般耗时在几十秒到数分钟。 
HA涉及到的主要实现逻辑有:

1) 主备需共享edit log存储。 
主NameNode和待命的NameNode共享一份edit log,当主备切换时,Standby通过回放edit log同步数据。 
共享存储通常有2种选择

  • NFS:传统的网络文件系统
  • QJM:quorum journal manager

QJM是专门为HDFS的HA实现而设计的,用来提供高可用的edit log。QJM运行一组journal node,edit log必须写到大部分的journal nodes。通常使用3个节点,因此允许一个节点失败,类似ZooKeeper。注意QJM没有使用ZK,虽然HDFS HA的确使用了ZK来选举主Namenode。一般推荐使用QJM。

2)DataNode需要同时往主备发送Block Report 
因为Block映射数据存储在内存中(不是在磁盘上),为了在Active NameNode挂掉之后,新的NameNode能够快速启动,不需要等待来自Datanode的Block Report,DataNode需要同时向主备两个NameNode发送Block Report。

3)客户端需要配置failover模式(失效备援模式,对用户透明) 

Namenode的切换对客户端来说是无感知的,通过客户端库来实现。客户端在配置文件中使用的HDFS URI是逻辑路径,映射到一对Namenode地址。客户端会不断尝试每一个Namenode地址直到成功。

4)Standby替代Secondary NameNode 
如果没有启用HA,HDFS独立运行一个守护进程作为Secondary Namenode。定期checkpoint,合并镜像文件和edit日志。

如果当主Namenode失败时,备份Namenode正在关机(停止 Standby),运维人员依然可以从头启动备份Namenode,这样比没有HA的时候更省事,算是一种改进,因为重启整个过程已经标准化到Hadoop内部,无需运维进行复杂的切换操作。

NameNode的切换通过代failover controller来实现。failover controller有多种实现,默认实现使用ZooKeeper来保证只有一个Namenode处于active状态。

每个Namenode运行一个轻量级的failover controller进程,该进程使用简单的心跳机制来监控Namenode的存活状态并在Namenode失败时触发failover。Failover可以由运维手动触发,例如在日常维护中需要切换主Namenode,这种情况graceful(优雅的) failover,非手动触发的failover称为ungraceful failover。

在ungraceful failover的情况下,没有办法确定失败(被判定为失败)的节点是否停止运行,也就是说触发failover后,之前的主Namenode可能还在运行。QJM一次只允许一个Namenode写edit log,但是之前的主Namenode仍然可以接受读请求。Hadoop使用fencing来杀掉之前的Namenode。Fencing通过收回之前Namenode对共享的edit log的访问权限、关闭其网络端口使得原有的Namenode不能再继续接受服务请求。使用STONITH技术也可以将之前的主Namenode关机。

最后,HA方案中Namenode的切换对客户端来说是不可见的,前面已经介绍过,主要通过客户端库来完成。

参考:HDFS概念相关笔记     深入理解Hadoop HDFS     HDFS 初识      HDFS原理了解

转载于:https://my.oschina.net/liyurong/blog/3042412

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值