Hadoop分布式文件系统HDFS

本文深入介绍了Hadoop分布式文件系统(HDFS)的架构、工作原理及关键特性,包括数据冗余存储策略、NameNode与DataNode角色、元数据管理、HA与Federation机制,以及通信协议等,帮助读者全面理解HDFS的运作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

分布式文件系统把文件分布式存储多个计算机节点上,成千上万的计算机节点构成计算机集群。

与使用多个处理器和专用高级硬件的并行化处理装置不同,目前分布式文件系统采用的计算机集群都是普通的硬件构成,这样就很大程度的降低了硬件上的开销。

分布式文件系统的结构

分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类,一类是 “主节点” :Master Node(也就是NameNode), 一类是“从节点”:Slave Node (也就是DataNode)。

大规模文件系统的整体结构如上图所示(图片来源: 林子雨教授的<<大数据技术原理与应用>>课件)

 

HDFS设计实现以下目标

兼容廉价的硬件设备

流数据读写

大数据集的存储

强大的跨平台兼容性

HDFS特殊设计带来的局限性

不适合低延迟数据访问

HDFS是为了高吞吐数据设计的,牺牲了延迟,如果要低延迟的数据访问,HBase更适合

无法高效存储大量小文件

因为文件的元数据(文件块的存储列表,目录结构等)存储在NameNode的内存中,这就导致了整个HDFS文件系统的文件数量受限于NameNode的内存大小,

不支持多用户写入,以及无法修改文件(文件上传到HDFS上后无法修改)

HDFS核心概念

blocks(块)

HDFS中默认一个块是128MB,一个大的文件会被分成多个block,以block作为存储单位。比block小的文件不会占用整个block,只会占据实际大小,例如,一个文件大小为10MB,则在HDFS中只会占用10MB的空间,而不会是128MB.

block大的好处

    可以最小化寻址开销,但是block不能设置过大,如果block设置过大的话,在mapreduce任务中,map或者reduce任务的个数如果小于集群机器数量,会使作业运行效率很低。

支持大规模文件存储

    文件以块为单位进行存储,一个大规模文件可以被分拆成若干个文件块,不同的文件可以被分发到不同的节点上,因此一个文件的大小不会受到单个节点的存储容量的限制,可以远远大于网络中任意记得的存储容量。因为一个很大的文件会被分为许多块。

简化系统设计

    因为文件块大小是固定的,这样可以很容易计算出一个节点可以存储多少文件块,其次,为了方便元数据的管理,元数据不需要和文件一起存储,可以由其他系统负责管理元数据

适合数据备份

    每个文件块东可以冗余存储到多个节点上,大大提高系统的容错性和可用性

NameNode & DataNode

    整个HDFS集群由NameNode和DataNode构成master-worker(主从)模式,NameNode和DataNode的主要功能如下表

NameNodeDataNode
存储元数据存储文件内容
元数据保存在内存中文件内容保存在磁盘中
保存文件,block,datanode之间的映射关系维护了block id 到 datanode本地文件的映射关系

NameNode

NameNode的数据结构

在HDFS中,NameNode负责管理分布式文件系统的命名空间(Namespace),保存了两个核心的数据结构:FSImage和EditLog

  1. FsImage用于维护文件系统树以及文件树中所有的文件和文件夹的元数据
  2. EditLog是操作日志文件,记录了所有针对文件的创建,删除,重命名等操作

 FsImage文件

FsImage文件包含文件系统中所有目录和文件inode的序列化形式,每个inode是一个文件或目录的元数据的内部表示,并且包含了这些信息:文件的复制等级、修改和访问 时间、访问权限、块大小以及组成文件的块。对于目录,则存储修改时间、权限和配 额元数据

FsImage文件没有记录块存储在哪个数据节点。而是由NameNode把这些映射保留在 内存中,当数据节点加入HDFS集群时,DataNode会把自己所包含的块列表告知给NameNode,此后会定期执行这种告知操作,以确保NameNode的块映射是最新的。

 

NameNode的启动过程

  1. 在NameNode启动的时候,它会将FsImage文件中的内容加载到内存中,之后再执行 EditLog文件中的各项操作,使得内存中的元数据和实际的同步,存在内存中的元数据支持客户端的读操作。
  2. 一旦在内存中成功建立文件系统元数据的映射,则创建一个新的FsImage文件和一个空的EditLog文件
  3. NameNode运行起来后,HDFS中的更新操作会重新写到EditLog文件中,而不是添加到FsImage中,因为FsImage文件一般都很大(GB级别的是常见),如果所有的操作都往FsImage中添加的会导致系统运行的十分缓慢。   但是,如果往EditLog文件里面写就不会这样 ,因为EditLog 要小很多。每次执行写操作之后,且在向客户端发送成功代码之前, edits文件(就是Edit Log)都需要同步更新

PS:由NameNode的启动过程可知,FsImage只有在启动时会改变,其他时间都是静态不变的,用户操作时改变的是EditLog文件。

名称节点运行期间EditLog不断变大的问题

在名称节点运行期间,HDFS的所有更新操作都是直接写到EditLog中,久而久之, EditLog文件将会变得很大,虽然在NameNode运行期间没有影响,但是当NameNode重启时,NameNode需要将FsImage里面的所有内容映像到内存中,然后再一条条的执行EditLog中的记录,当 EditLog文件非常大的时候,会导致NameNode启动操作非常慢,而在这段时间内HDFS系统处于 安全模式,一直无法对外提供写操作,影响了用户的使用

解决方法

通过 SecondaryNameNode 对FsImage和editLog文件的合并

第二名称节点是HDFS架构中的一个组成部分,它是用来保存名称节点中对HDFS 元数据信息的备份,并减少名称节点重启的时间。SecondaryNameNode一般是单独运 行在一台机器上。

合并的流程图如下

  1. SecondaryNameNode会定期和NameNode 通信,请求其停止使用EditLog文件,暂时将新的写操作写到一个新的文件edit.new上来,这个操 作是瞬间完成,上层写日志的函数完全感觉不到差别;
  2. SecondaryNameNode通过HTTP GET 方式从NameNode上获取到FsImage和EditLog文 件,并下载到本地的相应目录下;
  3. SecondaryNameNode将下载下来的 FsImage载入到内存,然后一条一条地执行 EditLog文件中的各项更新操作,使得内存中的 FsImage 保持最新;这个过程就是EditLog和 FsImage文件合并,合并后FsImage的文件就是最新的了
  4. SecondaryNameNode执行完合并操作之后,会通过post方式将新的FsImage文件发 送到NameNode节点上
  5. NameNode将从SecondaryNameNode 接收到的新的FsImage替换旧的FsImage文件, 同时将edit.new替换EditLog文件,通过这个过程 EditLog就变小了。(Edit Log文件不只一个)

DataNode

  1. 数据节点是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或者是名称节点的调度来进行数据的存储和检索,并且向NameNode定期发送自己 所存储的块的列表
  2. 每个数据节点中的数据会被保存在各自节点的本地Linux文件系统中

Block Caching

DataNode通常直接从磁盘读取数据,但是对频繁使用的Block块可以在内存中缓存,默认情况下,一个Block只有一个DataNode会缓存

作业调度器可以利用缓存提升性能,例如MapReduce可以把任务运行在有Block缓存的节点上。 
用户或者应用可以向NameNode发送缓存指令(缓存哪个文件,缓存多久), 缓存池的概念用于管理一组缓存的权限和资源。

HDFS Federation

我们知道NameNode的内存会制约文件数量(元数据存在内存中),HDFS Federation提供了一种横向扩展NameNode的方式。在Federation模式中,每个NameNode管理命名空间的一部分,例如一个NameNode管理/user目录下的文件, 另一个NameNode管理/share目录下的文件。 
每个NameNode管理一个namespace volumn,所有volumn构成文件系统的元数据。每个NameNode同时维护一个Block Pool,保存Block的节点映射等信息。各NameNode之间是独立的,一个节点的失败不会导致其他节点管理的文件不可用。 

HDFS HA*

在HDFS集群中,NameNode依然是单点故障(SPOF)。元数据同时写到多个文件系统以及Second NameNode定期checkpoint有利于保护数据丢失,但是并不能提高可用性。 
这是因为NameNode是唯一一个对文件元数据和file-block映射负责的地方, 当它挂了之后,包括MapReduce在内的作业都无法进行读写。

当NameNode故障时,常规的做法是使用元数据备份重新启动一个NameNode。元数据备份可能来源于:

多文件系统写入中的备份
Second NameNode的检查点文件
启动新的Namenode之后,需要重新配置客户端和DataNode的NameNode信息。另外重启耗时一般比较久,稍具规模的集群重启经常需要几十分钟甚至数小时,造成重启耗时的原因大致有: 
1) 元数据镜像文件载入到内存耗时较长。 
2) 需要重放edit log 
3) 需要收到来自DataNode的状态报告并且满足条件后才能离开安全模式提供写服务。

Hadoop的HA方案*

采用HA的HDFS集群配置两个NameNode,分别处于Active和Standby状态。当Active NameNode故障之后,Standby接过责任继续提供服务,用户没有明显的中断感觉。一般耗时在几十秒到数分钟,不像冷备份,恢复时间较长,恢复期间用户是无法访问。
HA涉及到的主要实现逻辑有

1) 主备需共享edit log存储。 
Active状态的NameNode和Standby状态的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通信协议都是构建在 TCP/IP协议基础之上
  • 客户端通过一个可配置的端口向NameNode发起TCP连接,并使用客户端协议与NameNode进行交互
  • NameNode与DataNode之间使用数据节点协议(DatanodeProtocol)进行交互
  • 客户端与数据节点的交互是通过RPC(Remote Procedure Call)来实现的。在设计上,NameNode不会主动发起RPC,而是响应来自客户端和DataNode的RPC请求

HDFS存储原理

冗余数据存储

作为一个分布式文件系统,为了保证系统的容错性和可用性,HDFS采用了多副本方式对数据进行冗余存储,通常一个数据块的多个副本会被分布到不同的数据节点 上,如图所示,数据块1被分别存放到数据节点A和C上,数据块2被存放在数据节 点A和B上。这种多副本方式具有以下几个优点:

数据存取策略

  • 第一个副本(Block1):放置在上传文件的数据节点;如果是集群外提交,则随机挑选一台磁盘 不太满、CPU不太忙的节点
  • 第二个副本(Block2):放置在与第一个副本不同的机架的节点上
  • 第三个副本(Block3):与第一个副本相同机架的其他节点上
  • 更多副本:随机节点

 

DataNode出错

  • 每个数据节点会定期向名称节点发送“心跳”信息,向名称节点报告自己的状态 (心跳机制)
  • 当DataNode发生故障,或者网络发生断网时,NameNode就无法收到来自一些DataNode的心跳信息,这时,这些DataNode就会被标记为“宕机”,节点上面的所有数据都会被标记为“不可读”,NameNode不会再给它们发送任何I/O请求
  • 这时,有可能出现一种情形,即由于一些DataNode的不可用,会导致一些数据块的 副本数量小于冗余因子(设置的副本数量) ,NameNode会定期检查这种情况,一旦发现某个数据块的副本数量小于冗余因子,就 会启动数据冗余复制,为它生成新的副本 
  • HDFS和其它分布式文件系统的最大区别就是可以调整冗余数据的位置

参考:

https://blog.youkuaiyun.com/bingduanlbd/article/details/51914550 


林子雨教授的 大数据技术原理与应用

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值