大数据系列-Hadoop-HDFS理念图解心法篇

网友投稿 240 2022-11-21

大数据系列-Hadoop-HDFS理念图解心法篇

​1、 什么是HDFS?​

在我们享受互联网应用的同时,应用本身会产生大量数据,但在应用的环境中,单机容量很难满足存储大量数据,一旦数据体量达到一定级别,我们就需要将数据存放在多台机器上存储,并进行统一的管理,这就是分布式文件系统称为DFS(Distributed File System)。

Hadoop为我们提供了分布式文件系统的整体解决方案,称为:HDFS (Hadoop Distributed File System),它通过集成多台机器的存储能力形成一个超大的存储空间,以分布式的凡是提供文件系统的横向扩展,并提供统一的接口进行访问,让使用者无需关心底层的复杂架构,使分布式文件存储像访问单个文件一样轻松。

2、 ​HDFS​在什么情况下适用?​

​虽然HDFS提供了分布式文件系统,但该文件系统具有自身的特性,需要根据特性本身来选择HDFS的使用场景,不能随意进行框架的选型,首先,HDFS具备高容错性、大文件存储、流式数据访问以及存储的横向扩展能力,但HDFS因为寻址时间长、适合读取大文件,且本身设计目的为了高吞吐数据传输用于离线计算,故对于延时要求非常低的应用还是不太适合,对于在Web应用集群中各个节点对于共享文件系统进行低延时写入、读取与共享的场景中HDFS并不是最好的选择。

需要注意的是,HDFS适用于存储大文件,原因在介绍后面核心组件NameNode中我会详细阐述。

3、 ​HDFS​核心组件详解​

​HDFS通过NameNode节点管理若干个存储数据的节点DataNode,我们可以理解为主从关系结构,NameNode负责管理各个节点的位置以及接收客户端对文件的访问请求,也就是类似于我们集群中的领导者角色,而集群中的DataNode为数据节点,每个节点上保存实际的数据,这里需要注意的是DataNode中数据存放位置是存储在DataNode所在机器中的文件系统,并且HDFS会对大体积的数据进行分块存储在不同的DataNode中。

如下图所示:

​可以看出HDFS由Client、NameNode、SecondaryNameNode、Block、DataNode以及元数据组成。对于理解这些组成部分对今后使用HDFS会有很大帮助。

​3.1 ​Block数据块

​在HDFS存储文件之前,文件会被划分成相同大小的多个文件块,作为最小的存储单元,在Hadoop1.x版本中默认数据块大小为64M,在Hadoop2.x版本中默认数据块的大小为128M,当然也可以在Hadoop中hdfs-site.xml文件中配置数据块的自定义大小。当然自定义数据块的大小需要根据场景、寻址开销与MR的任务相关。

dfs.blocksize 30m dfs.namenode.fs-limits.min-block-size 128m

3.2​ Client​​

​客户端Client主要通过一些命令对HDFS进行访问操作、数据读写,通过与NameNode交互获取数据的位置信息,根据位置信息与具体的DataNode进行实际的读写交互,在文件提交时,对大文件进行文件的切块,形成若干个Block数据块,根据NameNode提供的位置信息存储到对应的DataNode中,Client的交互可以分为多种包括命令行与API等。

3.3 ​NameNode​​

​NameNode在内存中对整个文件系统中数据块的目录结构、文件名、位置、权限、副本数等元数据进行管理,这些元数据信息会定期自动保存到NameNode所在服务器的本地磁盘中,通常在一个集群中只有一个NameNode处于激活状态,主要功能为:接收客户端读写操作、管理数据块副本、对DataNode节点进行监控,对于宕机的DataNode数据块进行重新赋值。

NameNode中描述了集群的元数据,且在内存中存储,也就是说集群中每一个文件存放的地址、名称与大小等信息都在NameNode的内存中记录,当HDFS中存放的都是小文件时,那么NameNode中就会记录所有小文件的元数据信息,这样就会导致,当HDFS中小文件非常多时,DataNode磁盘存放还有很大空间,但NameNode的内存大小受限的原因,内存中已经无法在记录新写入文件的任何信息,导致HDFS的利用率非常低,所有建议在HDFS中存放大文件,若存在必须存放小文件的情况,请将小文件合并成大文件后在HDFS中进行存储。

3.4 ​DataNode​​

​DataNode主要负责真实数据的存储,并且以数据块的形式存储本地文件系统中,客户端通过NameNode反馈的存储位置对DataNode数据进行存储,并且数据块的副本数可在文件提交时进行设置,默认情况下每个数据块会分配三个副本。

DataNode还会定期向NameNode上报当前健康状态以及数据块存储情况信息。用于通知NameNode在DataNode宕机的情况下可以准确的在将该DataNode中的数据块指向其他副本节点。

3.5 ​元数据​

​我们知道NameNode中维护了对HDFS中集群数据节点DataNode以及相关操作的元数据记录,元数据核心内容主要包括:edits与fsimage文件,说明如下:

Edits:它是元数据操作日志,对客户端操作的记录进行维护,在客户端进行写数据与修改数据时,首先在Edits中进行目录树的维护,同时在高可用架构中也可以存储在JournalNode组成的集群中。

Fsimage:它是元数据镜像文件,保存所有Edits写入或修改时所形成的最新目录树结构,代表当前最新目录,因Fsimage每次启动加载重绘目录树非常消耗服务器计算资源,所以由Edits记录所有变化的记录,由Fsimage根据记录绘制最新目录树,我们也可以将不同时间段的最新目录树设置镜像,也成为检查单CheckPoint。

3.6 SecondaryNameNode

​通过元数据的工作原理我们可以看出,NameNode中元数据在内存中存放,随着HDFS的内容与操作的不断增加,Edits内容也会不断变大,NameNode内存总会有枯竭的时候,SecondaryNameNode就是用来辅助NameNode定期对NameNode中的元数据Edits进行合并,形成最新Fsimage,清空NameNode内存中Edits并将合并阶段产生的Edits记录临时存放在一个新的内存空间中,将临时Edits记录应用于Edits中达到内存释放的效果。

​这里需要注意的是SecondaryNameNode只是NameNode的一个助手协助NameNode进行元数据管理,并不拥有NameNode的特性,所以它并不能保证集群的高可用。

4、 ​HDFS​副本策略与机架感知​

4.1 Block副本

​在HDFS中所有的文件都被划分为block块的方式存放在在 Hadoop1.x中, block 块默认大小是 64M, hadoop2.x中, 文件的 block 块大小默认是128M,,需要注意的是Block块只是一个逻辑空间,也就是说一个128M的块中如果只放了5M的数据,那么在实际存储空间中只占用5M。

4.2 副本放置策略机架感知

​从前面介绍的HDFS的适用场景可以了解到,HDFS自身是具备高容错性的,当一个数据节点宕机后,仍然可以有效的对数据进行读写等操作,那么就需要数据在存储时建立数据块Block的副本,若未设置数据副本数量默认为3个副本。

我们知道不管是HDFS中的任何节点,将来都需要部署运行在实际的机器中,机器假设在我们的机房中一排排的机架中,如何保证在某一排机架中所有机器宕机后仍然不影响数据的操作,也就是说HDFS中副本的放置位置的策略需要考虑到上述情景。俗称机架感知。

那么根据什么策略来控制副本的存放位置,我们成为副本存放策略,如下图所示:

第一步:客户端通过NameNode挑选一台满足存储空间的节点,进行副本1上传;

第二步:将副本二放置在与副本一所属机器不同机架的DataNode服务器节点中;

第三步:将副本三放置在与副本二同一个机架的DataNode服务器节点中。

从上述存储策略可以看出,不管是单节点故障还是多节点机架故障,HDFS可以通过副本机制与存放策略对所存储的内容实现高容错性。

5、 ​HDFS​读文件的过程​

​在开始了解概念的时候,我们认为HDFS是将多个文件系统组合成一个大的文件系统供我们使用,可以把它当作一个文件系统进行操作,我们也知道文件被分块存储在不同的DataNode节点中,那么如何通过HDFS进行文件的读取?Client客户端为我们提供了操作HDFS的相关操作,当然也可以通过命令行等其他方式,了解Client对HDFS的读取有利于我们在实际使用中的逻辑更加清晰以及问题排查更加容易。具体读取方式见下图:

​1.客户端通过FileSystem对象指定NameNode的地址,通过Open方法进行RPC调用NameNode获取文件块的位置信息;FileSystem对象指定NameNode的地址,通过Open方法进行RPC调用NameNode获取文件块的位置信息;

2.FileSystem的Open方法获取位置信息后,返回FSDataInputStream,建立了DataNode坐在位置的读取通道;

3.客户端通过FSDataInputStream会根据块地址对响应DataNode进行读取操作read方法;将数据从DataNode传输到客户端。当某个DataNode读取完成时,按照此步骤对下一个DataNod进行读取。

4.最后客户端一旦读取完成,可以通过调用FSDataInputStream的close方法,关闭读取通道。若需要将文件保存本地,可以使用FileOutPutStream执行保存路径,将FSDataInputStream流拷贝到FileOutPutStream流,完成后通过close方法关闭所有管道;

6、 ​HDFS​写文件的过程​

​我们发现读文件的过程是通过客户端生成FSDataInputStream来帮助我们从不同的DataNode中获取数据,相反写数据我们需要客户端生成FSDataOutputStream来帮助我们给DataNode写入数据,但是数据的写入过程可能与我们现在联想的过程不同,如下图:

​1.客户端通过FileSystem对象指定NameNode的地址,通过Create方法进行RPC调用NameNode获取文件块的存储位置信息,同时判断目标文件是否已存在,NameNode会根据副本策略返回存储的DataNode列表信息;

2.客户端通过FSDataOutputStream会根据块NameNode返回的列表选取最近的一台上传数据,并根据DataNode列表在DataNode之间建立管道。

3.Client开始将数据块提交到DataNode管道链条中的第一个DataNode,且由接收的DataNode一次通过管道将数据块传递给下一个DataNode直至数据传输完成;当一个 block 传输完成之后, Client 再次请求 NameNode 上传第二个 block到DataNode链条;

4.最后客户端一旦写入完成,客户端即关闭通道;

7、 HDFS高可用架构

​到此我们已经对HDFS的整体概念有了初步的了解,这时我们会发现,NameNode管理者整个HDFS集群,虽然DataNode节点群通过副本及副本策略实现了高容错性,但是一旦NameNode宕机,整个HDFS就会变成群龙无首,且SecondaryNameNode是个智能辅助NameNode的阿斗,所以,在实际生产环境中,我们需要对NameNode进行多分部署,并且正常情况下只启用一个NameNode处于活动状态,其他NameNode节点处于后备节点。如下图:

​本图我们不需要关注Yarn与MapReduce部分,只需要关注Zookeeper、JournalNode与HDFS部分,我们可以看到我们通过Zookeeper对NameNode节点状态进行监控与管理,通过NameNode中ZKFC与Zookeeper进行通信,利用Zookeeper选举机制切换NameNode,同时在切换NameNode时,新上任的NameNode需要提供与原NameNode相同的元数据描述,我们通过JournalNode集群实现元数据在NameNode之间的共享。详细介绍如下:

NameNode:NameNode在高可用模式下可以由2到多个,且有两种状态分别为:Active活动与Standby备份,且只有一个处于Active状态,其他节点均为Standby状态;

ZooKeeperFailoverController(ZKFC):ZKFC是基于Zookeeper的故障转移控制器,它负责控制NameNode的主备切换,ZKFC用于监测和控制NameNode的健康状态,当发现NameNode出现异常宕机后,通知Zookeeper进行一次新的选举,完成一次备份NameNode到活动NameNode的切换;

JouralNode:JouralNode集群负责收集同步ActiveNameNode节点中的元数据(edits fsiamge等),用于在ActiveNameNode宕机后,新的ActiveNameNode可以第一时间拿到元数据继续进行服务。

此时,我们会想即使JouralNode实现了元数据共享,但是NameNode的内存始终是有限的,当HDFS集群规模大到一定程度后,NameNode节点使用的内存可能会达到上限,那么集群的大小,存储的规模就受限于NameNode的资源性能,为了解决此问题可以通过Hadoop的联邦机制对NameNode进行水平扩展,鉴于本片文字长度问题,下一篇我们主要了解联邦机制。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:上海灵动微电子M0内核32位单片机MM32F0140
下一篇:maven项目无法读取到resource文件夹的问题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~