一文弄懂HDFS基本原理和架构

概述

HDFS(Hadoop Distributed File System),作为Google File System(GFS)的实现,是Hadoop项目的核心子项目,是分布式计算中数据存储管理的基础,是基于流数据模式访问和处理超大文件的需求而开发的,可以运行于廉价的商用服务器上。它所具有的高容错、高可靠性、高可扩展性、高获得性、高吞吐率等特征为海量数据提供了不怕故障的存储,为超大数据集(Large Data Set)的应用处理带来了很多便利。

官网:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html

适用、不适用的场景

HDFS特点:

  • 高容错性、可构建在廉价机器上

  • 适合批处理

  • 适合大数据处理

  • 流式文件访问

HDFS局限:

  • 不支持低延迟访问

  • 不适合小文件存储

  • 不支持并发写入:一个文件只能有一个写,不允许多个线程同时写。

  • 不支持修改:仅支持数据 append(追加),不支持文件的随机修改。

HDFS架构(Hadoop1.x)

在这里插入图片描述
HDFS由四部分组成,HDFS Client、NameNode、DataNode和Secondary NameNode。
HDFS是一个主/从(Master/Slave)体系结构,HDFS集群拥有一个NameNode和一些DataNode。NameNode管理文件系统的元数据,DataNode存储实际的数据(Block默认64M)。

Client

1、提供一些命令来管理、访问 HDFS,比如启动或者关闭HDFS。
2、与 DataNode 交互,读取或者写入数据;读取时,要与 NameNode 交互,获取文件的位置信息;写入 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储。

NameNode(Master)

1、管理 HDFS 的名称空间。
2、管理数据块(Block)映射信息
3、配置副本策略
4、处理客户端读写请求。

DataNode(Slave)

1、存储实际的数据块。
2、执行数据块的读/写操作。

Secondary NameNode

1、辅助 NameNode,分担其工作量。
2、定期合并 fsimage和fsedits,并推送给NameNode。
3、在紧急情况下,可辅助恢复 NameNode。
注:并非 NameNode 的热备。当NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务。

HDFS 副本存放策略

在这里插入图片描述

NameNode工作原理

NameNode主要负责三个功能,分别是;(1)管理元数据 ;(2)维护目录树; (3)响应客户请求

NameNode元数据三种存储形式:

  • 1.内存metadata(NameSystem)

  • 2.磁盘元数据镜像文件(fsImage)

  • 3.数据操作日志文件(edits)

注:NameSystem = fsImage + edits;当客户端对hdfs中的文件进行新增或者修改操作,操作记录首先被记入edits日志文件中,当客户端操作成功后,相应的元数据会更新到内存metadata中
在这里插入图片描述
namenode工作机制:

(1)第一次启动namenode格式化后,创建fsimage和edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。

(2)客户端对元数据进行增删改的请求

(3)namenode记录操作日志,更新滚动日志。

(4)namenode在内存中对数据进行增删改查

注:

<1>存储文件的metadata,运行时所有数据都保存在内存中,这个的HDFS可存储的文件受限于NameNode的内存,因此,NameNode节点的内存一般都较大。

<2>NameNode失效则整个HDFS都失效了,所以要保证NameNode的可用性(SecondNameNode非NameNode的热备)。

SecondNameNode与NameNode交互

在这里插入图片描述
SecondaryNameNode主要有两个作用:一是镜像备份;另一个是辅助合并NameNode的edit logs到fsimage文件中。
日志与镜像的定期合并总共分五步:
1、SecondaryNameNode通知NameNode准备提交edits文件,此时主节点产生edits.new
2、SecondaryNameNode通过http get方式获取NameNode的fsimage与edits文件(在SecondaryNameNode的current同级目录下可见到 temp.check-point或者previous-checkpoint目录,这些目录中存储着从namenode拷贝来的镜像文件)
3、SecondaryNameNode开始合并获取的上述两个文件,产生一个新的fsimage文件fsimage.ckpt
4、SecondaryNameNode用http post方式发送fsimage.ckpt至NameNode
5、NameNode将fsimage.ckpt与edits.new文件分别重命名为fsimage与edits,然后更新fstime,整个checkpoint过程到此结束。

通常情况下,SecondaryNameNode每隔一小时执行一次。 可以调整设置(hdfs-site.xml):

<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
<description>操作动作次数</description>
</property>

<property>
<name>dfs.namenode.checkpoint.check.period</name>
<value>60</value>
<description> 1 分钟检查一次操作次数</description>
</property>

DataNode与NameNode交互

在这里插入图片描述
DataNode就是HDFS的工作节点了,它负责存储数据,为客户端提供数据块的读写服务。在启动时会将它存储的数据块的列表发送给NameNode,根据NameNode的要求对数据块进行创建、删除和备份,还会通过心跳定期向NameNode更新存储数据块信息。
(1)一个数据块在datanode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
(2)DataNode启动后向namenode注册,通过后,周期性(1小时)的向namenode上报所有的块信息。
(3)心跳是每3秒一次,心跳返回结果带有namenode给该datanode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个datanode的心跳,则认为该节点不可用。
(4)集群运行中可以安全加入和退出一些机器。

HDFS读写机制

HDFS 如何读取文件

在这里插入图片描述
HDFS的文件读取原理,主要包括以下几个步骤:

  • 首先调用FileSystem对象的open方法,其实获取的是一个DistributedFileSystem的实例。
  • DistributedFileSystem通过RPC(远程过程调用)获得文件的第一批block的locations,同一block按照重复数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面。
  • 前两步会返回一个FSDataInputStream对象,该对象会被封装成 DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream就会找出离客户端最近的datanode并连接datanode。
  • 数据从datanode源源不断的流向客户端。
  • 如果第一个block块的数据读完了,就会关闭指向第一个block块的datanode连接,接着读取下一个block块。这些操作对客户端来说是透明的,从客户端的角度来看只是读一个持续不断的流。
  • 如果第一批block都读完了,DFSInputStream就会去namenode拿下一批blocks的location,然后继续读,如果所有的block块都读完,这时就会关闭掉所有的流。

HDFS 如何写入文件

在这里插入图片描述
HDFS的文件写入原理,主要包括以下几个步骤:

  • 客户端通过调用 DistributedFileSystem 的create方法,创建一个新的文件。
  • DistributedFileSystem 通过 RPC(远程过程调用)调用 NameNode,去创建一个没有blocks关联的新文件。创建前,NameNode 会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,NameNode 就会记录下新文件,否则就会抛出IO异常。
  • 前两步结束后会返回 FSDataOutputStream 的对象,和读文件的时候相似,FSDataOutputStream 被封装成 DFSOutputStream,DFSOutputStream 可以协调 NameNode和 DataNode。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小packet,然后排成队列 data queue。
  • DataStreamer 会去处理接受 data queue,它先问询 NameNode 这个新的 block 最适合存储的在哪几个DataNode里,比如重复数是3,那么就找到3个最适合的 DataNode,把它们排成一个 pipeline。DataStreamer 把 packet 按队列输出到管道的第一个 DataNode 中,第一个 DataNode又把 packet 输出到第二个 DataNode 中,以此类推。
  • DFSOutputStream 还有一个队列叫 ack queue,也是由 packet 组成,等待DataNode的收到响应,当pipeline中的所有DataNode都表示已经收到的时候,这时akc queue才会把对应的packet包移除掉。
  • 客户端完成写数据后,调用close方法关闭写入流。
  • DataStreamer 把剩余的包都刷到 pipeline 里,然后等待 ack 信息,收到最后一个 ack 后,通知 DataNode 把文件标示为已完成。

HDFS新特性(Hadoop2.x)

Hadoop2.x中HDFS的变化主要体现在增强了NameNode的水平扩展(Horizontal Scalability)及高可用性(HA)。

单个Namenode的HDFS架构的局限性

(1)Namespace(命名空间)的限制
由于Namenode在内存中存储所有的元数据(metadata),因此单个Namenode所能存储 的对象(文件+块)数目受到Namenode所在JVM的heap size的限制。50G的heap能够存储20亿(200 million)个对象,这20亿个对象支持4000个datanode,12PB的存储(假设文件平均大小为40MB)。
(2)性能的瓶颈
由于是单个Namenode的HDFS架构,因此整个HDFS文件系统的吞吐量受限于单个Namenode的吞吐量。
(3)隔离问题
由于HDFS仅有一个Namenode,无法隔离各个程序,因此HDFS上的一个实验程序就很有可 能影响整个HDFS上运行的程序。那么在HDFS Federation中,可以用不同的Namespace来 隔离不同的用户应用程序,使得不同Namespace Volume中的程序相互不影响。
(4)单点故障
在只有一个Namenode的HDFS中,此Namenode的宕机无疑会导致整个集群不可用。(SecondNameNode不是HA,它只是阶段性的合并 edits 和 fsimage)

HDFS Federation

单 NN 的架构使得 HDFS 在集群扩展性和性能上都有潜在的问题,当集群大到一定程度后,NN 进程使用的内存可能会达到上百 G,常用的估算公式为 1G 对应 1 百万个块,按缺省块大小计算的话,大概是 64T (这个估算比例是有比较大的富裕的,其实,即使是每个文件只有一个块,所有元数据信息也不会有 1KB/block)。同时,所有的元数据信息的读取和操作都需要与 NN 进行通信,譬如客户端的 addBlock、getBlockLocations,还有 DataNode 的 blockRecieved、sendHeartbeat、blockReport,在集群规模变大后,NN 成为了性能的瓶颈。Hadoop 2.0 里的 HDFS Federation 就是为了解决这两个问题而开发的。
官网 HDFS Federation:http://hadoop.apache.org/docs/r3.0.3/hadoop-project-dist/hadoop-hdfs/Federation.html
在这里插入图片描述
Federation,中文翻译为联邦,多个 NN 共用一个集群里的存储资源,每个 NN 都可以单独对外提供服务。每个 NN 都会定义一个存储池,有单独的 id,每个 DN 都为所有存储池提供存储。DN 会按照存储池 id 向其对应的 NN 汇报块信息,同时,DN 会向所有 NN 汇报本地存储可用资源情况。
几个关键概念

  • Block Pool 块池: 一个Block Pool是属于同一个namespace下的一组块集合。每个datanode可能会存储集群中所有Block Pool的数据块。(Datanodes store blocks for all the block pools in the cluster.)每个Block Pool的管理是独立的。这样的好处是,允许一个namespace为一个新的块生成一个Block IDs,而不需要和其他的namespace进行协调。一个namenode挂掉了,不会影响其他namenode。
  • Namespace Volume: 一个namespace和它的Block Pool一起被统称为Namespace Volume。它是管理的最小单元。当一个Namenode/namespace被删除之后,每个Datanode上相应的Block Pool也会被删除。每个Namespace Volume是升级的最小的一个单元。
  • ClusterID: 一个新的标识ClusterID添加到集群,用来标记所有的Nodes,当Namenode格式化时(formated),将会自动创建ClusterID,这个ID用来区分集群中的Namenodes。

总结:

  • 多个 NN 共用一个集群里 DN 上的存储资源,每个 NN 都可以单独对外提供服务
  • 每个 NN 都会定义一个存储池,有单独的 id,每个 DN 都为所有存储池提供存储
  • DN 会按照存储池 id 向其对应的 NN 汇报块信息,同时,DN 会向所有 NN 汇报本地存储可用资源情况
  • 如果需要在客户端方便的访问若干个 NN 上的资源,可以使用客户端挂载表,把不同的目录映射到不同的 NN,但 NN 上必须存在相应的目录

HDFS HA(高可用)

官网 HDFS High Availability Using the Quorum Journal Manager:http://hadoop.apache.org/docs/r3.0.3/hadoop-project-dist/hadoop-hdfs/HDFSHighAvailabilityWithQJM.html
在这里插入图片描述
HA的大致架构,其设计上的考虑包括:

  • 利用共享存储来在两个NN间同步edits信息。
  • DataNode(以下简称DN)同时向两个NN汇报块信息。
  • 用于监视和控制NN进程的FailoverController进程

我们不能在NN进程内进行心跳等信息同步,最简单的原因,一次FullGC就可以让NN挂起十几分钟,所以,必须要有一个独立的短小精悍的watchdog来专门负责监控。这也是一个松耦合的设计,便于扩展或更改,目前版本里是用ZooKeeper(以下简称ZK)来做同步锁,但用户可以方便的把这个ZooKeeper FailoverController(以下简称ZKFC)替换为其他的HA方案或leader选举方案。

  • 隔离(Fencing),防止脑裂,就是保证在任何时候只有一个主NN,包括三个方面:

1.共享存储fencing,确保只有一个NN可以写入edits。
2.客户端fencing,确保只有一个NN可以响应客户端的请求。
3.DataNode fencing,确保只有一个NN可以向DN下发命令,譬如删除块,复制块,等等。

基于QJM的HA方案

在这里插入图片描述
见另一篇《一文弄懂HDFS的Ha高可用原理》

主备切换

在这里插入图片描述
从图中可以看出,整个切换过程是由ZKFC来控制的,具体又可分为HealthMonitor、ZKFailoverController和ActiveStandbyElector三个组件。

  • ZKFailoverController: 是HealthMontior和ActiveStandbyElector的母体,执行具体的切换操作
  • HealthMonitor: 监控NameNode健康状态,若状态异常会触发回调ZKFailoverController进行自动主备切换
  • ActiveStandbyElector: 通知ZK执行主备选举,若ZK完成变更,会回调ZKFailoverController相应方法进行主备状态切换

在故障切换期间,ZooKeeper主要是发挥什么作用呢,有以下几点:

  • 失败保护:集群中每一个NameNode都会在ZooKeeper维护一个持久的session,机器一旦挂掉,session就会过期,故障迁移就会触发
  • Active NameNode选择:ZooKeeper有一个选择ActiveNN的机制,一旦现有的ANN宕机,其他NameNode可以向ZooKeeper申请排他成为下一个Active节点
  • 防脑裂: ZK本身是强一致和高可用的,可以用它来保证同一时刻只有一个活动节点

那在哪些场景会触发自动切换呢,从HDFS-2185中归纳了以下几个场景:

  • ActiveNN JVM奔溃:ANN上HealthMonitor状态上报会有连接超时异常,HealthMonitor会触发状态迁移至SERVICE_NOT_RESPONDING, 然后ANN上的ZKFC会退出选举,SNN上的ZKFC会获得Active Lock, 作相应隔离后成为Active结点。
  • ActiveNN JVM冻结:这个是JVM没奔溃,但也无法响应,同奔溃一样,会触发自动切换。
  • ActiveNN 机器宕机:此时ActiveStandbyElector会失去同ZK的心跳,会话超时,SNN上的ZKFC会通知ZK删除ANN的活动锁,作相应隔离后完成主备切换。
  • ActiveNN 健康状态异常: 此时HealthMonitor会收到一个HealthCheckFailedException,并触发自动切换。
  • Active ZKFC奔溃:虽然ZKFC是一个独立的进程,但因设计简单也容易出问题,一旦ZKFC进程挂掉,虽然此时NameNode是OK的,但系统也认为需要切换,此时SNN会发一个请求到ANN要求ANN放弃主结点位置,ANN收到请求后,会触发完成自动切换。
  • ZooKeeper奔溃:如果ZK奔溃了,主备NN上的ZKFC都会感知断连,此时主备NN会进入一个NeutralMode模式,同时不改变主备NN的状态,继续发挥作用,只不过此时,如果ANN也故障了,那集群无法发挥Failover, 也就不可用了,所以对于此种场景,ZK一般是不允许挂掉到多台,至少要有N/2+1台保持服务才算是安全的。

HA和Federation部署结构图

在这里插入图片描述
就是 NameService。Hadoop 2.0 里对 NN 进行了一层抽象,提供服务的不再是 NN 本身,而是 NameService(以下简称 NS)。Federation 是由多个 NS 组成的,每个 NS 又是由一个或两个 (HA)NN 组成的。
图中 DN-1 到 DN-6 是六个 DataNode,NN-1 到 NN-4 是四个 NameNode,分别组成两个 HA 的 NS,再通过 Federation 组合对外提供服务。Storage Pool 1 和 Storage Pool 2 分别对应这两个 NS。我们在客户端进行了挂载表的映射,把 /share 映射到 NS1,把 /user 映射到 NS2,这个映射其实不光是要指定 NS,还需要指定到其上的某个目录。
配置见:hadoop2.0 federation与HA的配置

常见关键问题

NameNode如何防止脑裂

1、共享存储的fencing,确保只有一个NN能写成功。使用QJM实现fencing。
2、datanode的fencing。确保只有一个NN能命令DN。
(a) 每个NN改变状态的时候,向DN发送自己的状态和一个序列号。
(b) DN在运行过程中维护此序列号,当failover时,新的NN在返回DN心跳时会返回自己的active状态和一个更大的序列号。DN接收到这个返回是认为该NN为新的active。
© 如果这时原来的active(比如GC)恢复,返回给DN的心跳信息包含active状态和原来的序列号,这时DN就会拒绝这个NN的命令。
(d) 特别需要注意的一点是,上述实现还不够完善,HDFS-1972中还解决了一些有可能导致误删除block的隐患,在failover后,active在DN汇报所有删除报告前不应该删除任何block。
3、客户端fencing,确保只有一个NN能响应客户端请求。

hadoop2高可用并取代SecondaryNamenode

hadoop2.0的HA 机制有两个namenode,一个是active namenode,状态是active;另外一个是standby namenode,状态是standby。两者的状态是可以切换的,但不能同时两个都是active状态,最多只有1个是active状态。只有active namenode提供对外的服务,standby namenode是不对外服务的。active namenode和standby namenode之间通过NFS或者JN(journalnode,QJM方式)来同步数据。

active namenode会把最近的操作记录写到本地的一个edits文件中(edits file),并传输到NFS或者JN中。standby namenode定期的检查,从NFS或者JN把最近的edit文件读过来,然后把edits文件和fsimage文件合并成一个新的fsimage,合并完成之后会通知active namenode获取这个新fsimage。active namenode获得这个新的fsimage文件之后,替换原来旧的fsimage文件。

这样,保持了active namenode和standby namenode的数据的实时同步,standby namenode可以随时切换成active namenode(譬如active namenode挂了)。而且还有一个原来hadoop1.0的secondarynamenode,checkpointnode,buckcupnode的功能:合并edits文件和fsimage文件,使fsimage文件一直保持更新。所以启动了hadoop2.0的HA机制之后,secondarynamenode,checkpointnode,buckcupnode这些都不需要了。

hdfs块大小的变化?

Hadoop1.x都是64M,hadoop2.x开始都是128M。

参考

HDFS核心技术详解:https://blog.csdn.net/wypersist/article/details/79757242
HDFS文件系统:https://blog.csdn.net/c391183914/article/details/78658486
HDFS的NameNode工作机制:https://www.cnblogs.com/yaboya/p/9193508.html
HDFS-DataNode工作机制:https://my.oschina.net/u/3091870/blog/3000611
High
Availability
for
the
HDFS
Namenode:https://issues.apache.org/jira/browse/HDFS-1623
Hadoop 2.0 NameNode HA 和 Federation 实践:https://www.infoq.cn/article/hadoop-2-0-namenode-ha-federation-practice-zh
hadoop2—namenode—HA原理详解:https://www.cnblogs.com/sy270321/p/4398815.html
HDFS Federation HA 混合环境介绍:https://www.jianshu.com/p/80582687851f
hadoop2.0 federation与HA的配置:https://blog.51cto.com/sstudent/1392447
HDFS HA和Federation安装部署方法:http://dongxicheng.org/hadoop-hdfs/hdfs-ha-federation-deploy/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值