HDFS 面试篇《一》
  GPYyDLfgzzIb 2023年11月02日 44 0

HDFS 面试篇《一》_元数据

HDFS 面试篇《一》_客户端_02

一、数据块(block)

HDFS原理白话讲就是将大文件分为若干个块,将这些块散落在不同的服务器上进行存储。

1.1 数据块大小如何设置

在hdfs配置文件hdfs-site.xml中,通过dfs.blocksize参数配置

HDFS 面试篇《一》_客户端_03

1.2 为什么hdfs的数据块这么大

hadoop 1.x默认块大小为64M,hadoop 2.x默认块大小为128M,hadoop3.x默认块大小为256M

数据块大小设置部分原因是和磁盘平均输出速率有关。例如寻址时间是10ms,磁盘平均输出速率为125M/s,假如让寻址时间占总传输时间的1%,那么传输时间即为1s,以这个磁盘平均输出速率计算,大概可以传输125M的数据。所以数据块设置比较大是为了减少总寻址时间。

如果数据块设置太大,对于计算(例如mapreduce)的压力就会比较大,以mapreduce来说,一个map至少处理一个block,如果block设置特别大,就会影响处理的效率。

如果数据块设置太小,就意味着map处理的数据量就会特别小,而map在处理的时候会开java虚拟机,开虚拟机也需要时间消耗,就有可能开虚拟机的时间远远大于处理数据的时间,同样也会造成效率低的问题;另外,block的信息都在namenode中存储,同样一个大文件,数据块设置太小,就意味着分的数据块越多,那么对应的元数据信息也就越多,对于namenode来说压力也就越大。

1.3 block的一些操作

1.3.1 设置文件副本数,有什么用?

数据分块存储和副本的存放,是保证可靠性和高性能的关键

方式一:使用命令设置文件副本数;动态生效,不需要重启hadoop集群

用途一般在降低磁盘使用率的时候会用到,如果删除数据还解决不了磁盘使用率高的问题,那么就将一部分数据的副本数减少,从而临时解决磁盘使用率过高的问题。

hadoop fs -setrep -R 4 /path

方式二:修改配置文件hdfs-site.xml,需要重启hadoop集群才能生效

<property>
	<name>dfs.replication</name>
	<value>4</value>
</property>

1.3.2 HDFS提供了fsck命令

①用于检查HDFS上文件和目录的健康状态、获取文件的block信息和位置信息

hdfs fsck

HDFS 面试篇《一》_数据_04

查看文件中损坏的块

hdfs fsck /test/test.txt -list-corruptfileblocks

HDFS 面试篇《一》_元数据_05

查看文件的块基本信息

HDFS 面试篇《一》_客户端_06

④删除损坏的文件

hdfs fsck /test/test.txt -delete

HDFS 面试篇《一》_客户端_07

二、DataNode

部署datanode守护进程的节点叫做datanode节点。

datanode节点用来存储block。

2.1 副本数默认是多少,如何设置

hadoop默认副本数为3,可在hdfs-site.xml中通过dfs.replication参数设置

HDFS 面试篇《一》_元数据_08

2.2 多副本存放策略

1个datanode节点存放某个block的一个副本

第一个副本存储在同Client相同节点上;

第二个副本存储在不同机架的节点上;

第三个副本存储在第二个副本机架中的另外一个节点上;

其他副本选择随机存储。

三、NameNode & SecondaryNameNode

3.1 namenode的作用

          NameNode负责:文件元数据信息的操作以及处理客户端的请求

          NameNode管理:HDFS文件系统的命名空间NameSpace

          NameNode维护:文件系统树(FileSystem)以及文件树中所有的文件和文件夹的元数据信息(matedata),维护文件到块的对应关系和块到节点的对应关系

          NameNode文件:namespace镜像文件(fsimage),操作日志文件(edit log)。这些信息被Cache在RAM中,当然这两个文件也会被持久化存储在本地硬盘

          NameNode记录:每个文件中各个块所在的数据节点的位置信息。但它并不永久保存块的位置信息,因为这些信息在系统启动时由数据节点重建

          从数据节点重建:在nameNode启动时,DataNode向NameNode进行注册时发送给NameNode

【命名空间和元数据】

  • 元数据
  • 关于文件或目录的描述信息,如文件所在路径、文件名称、文件类型等等,这些信息称为文件的元数据metadata
  • 命名空间
  • 文件系统中,为了便于管理存储介质上的,给每个目录、目录中的文件、子目录都起了名字,这样形成的层级结构,称之为命名空间
  • 同一个目录中,不能有同名的文件或目录
  • 这样通过目录+文件名称的方式能够唯一的定位一个文件

edits.log的存放路径为hdfs-site.xml中属性dfs.namenode.edits.dir的值决定;

fsimage的存放路径为hdfs-site.xml中属性dfs.namenode.name.dir的值决定。

3.2 namenode的工作流程

第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,先加载Fsimage文件到内存中,然后加载Edits文件到内存中。并给Edits文件打标记,并生成一个空的edits_inprogress文件。此时NameNode内存就持有最新的元数据信息。

Client开始对NameNode发送元数据的增删改的请求,这些请求的操作首先会被记录到edits_inprogress中(查询元数据的操作不会被记录在Edits中,因为查询操作不会更改元数据信息 )

HDFS 面试篇《一》_元数据_09

3.3 元数据信息存放在namenode的内存中还是磁盘中

内存中存有一份完整的元数据meta.data

磁盘中同样存在一份元数据镜像fsimage

edits保存内存meta.data和磁盘元数据镜像fsimage之间的操作日志

HDFS 面试篇《一》_客户端_10

Fsimage:NameNode内存中元数据序列化后形成的文件,是HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统中所有的目录和文件inode的序列化信息。

Edits:记录客户端更新元数据信息的每一步操作 (可通过Edits运算出元数据),Edits文件,存放HDFS文件系统的所有更新操作的路径操作,文件系统客户端执行的所有写操作首先会被记录到Edits文件中。seen_txid文件保存的是一个数字,是最后一个edits_的数字。

详细一点:

因为元数据信息需要进行随机访问,还有响应客户请求,所以元数据信息存储在内存中效率才会最大化,因此,元数据需要存放在内存中

但如果只存在内存中,一旦断电,元数据丢失,整个集群就无法工作了。因此产生在磁盘中备份元数据的FsImage,即持久化。

这样又会带来新的问题,当在内存中的元数据更新时,如果同时更新FsImage,就会导致效率过低,但如果不更新,就会发生一致性问题,一旦NameNode节点断电,就会产生数据丢失。因此,引入Edits文件(只进行追加操作,效率很高)。每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中。这样,一旦NameNode节点断电,可以通过FsImage和Edits的合并,合成元数据。

但是,如果长时间添加数据到Edits中,会导致该文件数据过大,效率降低,而且一旦断电,恢复元数据需要的时间过长。因此,需要定期进行FsImage和Edits的合并,如果这个操作由NameNode节点完成,又会效率过低。因此,引入一个新的节点SecondaryNamenode,专门用于FsImage和Edits的合并。

3.4 SecondaryNamenode工作流程

  • SecondaryNameNode的作用就是帮助NameNode进行Edits和Fsimage的合并工作

(1)namenode节点每隔一定时间或者edits.log达到指定大小(lfs.checkpoint.period 指定两次checkpoint的最大时间间隔,默认3600秒;lfs.checkpoint.size    规定edits文件的最大值,一旦超过这个值则强制checkpoint,不管是否到达最大时间间隔。默认大小是64M),请求secondaryNamenode合并操作

(2)secondaryNamenode请求namenode进行edits.log的滚动,这样新的编辑操作就能够进入新的文件edits.new中

(3)secondaryNamenode从namenode中下载fsImage和edits.log

(4)secondaryNamenode进行fsImage和edits.log的合并,成为fsImage.checkpoint文件

(5)namenode下载合并后的fsImage.checkpoin文件

(6)将fsImage.checkpoint和edits.new命名为原来的文件名(之后fsImage和日志文件edits.log重新恢复初始状态)

NN和SNN对内存的消耗几乎是一致的,因此NN和SNN分别部署在两个不同节点上。

SNN对NN属于冷备。

四、HDFS架构

HDFS也是主从架构Master|Slave或称为管理节点|工作节点


HDFS 面试篇《一》_元数据_11

HDFS 面试篇《一》_数据_12

4.1 hdfs数据写流程

4.1.1详细流程

  • 创建文件:
  • HDFS客户端向HDFS写数据,先调用DistributedFileSystem.create()方法,在HDFS创建新的空文件
  • RPC(ClientProtocol.create())远程过程调用NameNode(NameNodeRpcServer)的create(),首先在HDFS目录树指定路径添加新文件
  • 然后将创建新文件的操作记录在editslog中
  • NameNode.create方法执行完后,DistributedFileSystem.create()返回FSDataOutputStream,它本质是封装了一个DFSOutputStream对象
  • 建立数据流管道:
  • 客户端调用DFSOutputStream.write()写数据
  • DFSOutputStream调用ClientProtocol.addBlock(),首先向NameNode申请一个空的数据块
  • addBlock()返回LocatedBlock对象,对象包含当前数据块的所有datanode的位置信息
  • 根据位置信息,建立数据流管道
  • 向数据流管道pipeline中写当前块的数据:
  • 客户端向流管道中写数据,先将数据写入一个检验块chunk中,大小512Byte,写满后,计算chunk的检验和checksum值(4Byte)
  • 然后将chunk数据本身加上checksum,形成一个带checksum值的chunk(516Byte)
  • 保存到一个更大一些的结构packet数据包中,packet为64kB大小
  • packet写满后,先被写入一个dataQueue队列中0
  • packet被从队列中取出,向pipeline中写入,先写入datanode1,再从datanoe1传到datanode2,再从datanode2传到datanode3中
  • 一个packet数据取完后,后被放入到ackQueue中等待pipeline关于该packet的ack的反馈
  • 每个packet都会有ack确认包,逆pipeline(dn3 -> dn2 -> dn1)传回输出流
  • 若packet的ack是SUCCESS成功的,则从ackQueue中,将packet删除;否则,将packet从ackQueue中取出,重新放入dataQueue,重新发送
  • 如果当前块写完后,文件还有其它块要写,那么再调用addBlock方法(流程同上
  • 文件最后一个block块数据写完后,会再发送一个空的packet,表示当前block写完了,然后关闭pipeline
  • 所有块写完,close()关闭流
  • ClientProtocol.complete()通知namenode当前文件所有块写完了

4.1.2容错

在写的过程中,pipeline中的datanode出现故障(如网络不通),输出流如何恢复

  • 输出流中ackQueue缓存的所有packet会被重新加入dataQueue
  • 输出流调用ClientProtocol.updateBlockForPipeline(),为block申请一个新的时间戳,namenode会记录新时间戳
  • 确保故障datanode即使恢复,但由于其上的block时间戳与namenode记录的新的时间戳不一致,故障datanode上的block进而被删除
  • 故障的datanode从pipeline中删除
  • 输出流调用ClientProtocol.getAdditionalDatanode()通知namenode分配新的datanode到数据流pipeline中,并使用新的时间戳建立pipeline
  • 新添加到pipeline中的datanode,目前还没有存储这个新的block,HDFS客户端通过DataTransferProtocol通知pipeline中的一个datanode复制这个block到新的datanode中
  • pipeline重建后,输出流调用ClientProtocol.updatePipeline(),更新namenode中的元数据
  • 故障恢复完毕,完成后续的写入流程

-----------------------------------------------------------------------------------------------------------------------------

1、首先client将文件缓存在本地临时文件中,当临时文件累计的大小为128M(设置的块大小)的block,然后调用客户端对象DistributedFileSystem的create方法,DistributedFileSystem跟NameNode通信请求创建一个文件

2、NameNode收到请求后会进行各种各样的检查,确保要创建的文件不存在,并且客户端有创建文件的权限。如果检查通过,NameNode会在edits log中写入创建文件的操作。否则创建失败,客户端抛出异常。

3、DistributedFileSystem返回一个FSDataOutputStream对象给客户端用来写数据。FSDataOutputStream封装了一个DFSOoutputStream用来跟DataNode和NameNode通信。

4、FSDataOutputStream将block块切分成许多64k大小的小数据包,并将这些小数据包写入到内部队列中(数据队列中)

5、DataStream会读取队列内容,并请求NameNode返回一个DataNode列表来存储当前的block副本

6、列表中的DataNode会形成管线,DataStream将数据包发送给第一个DataNode,然后第一个发给第二个,第二个发给第三个

7、DFSOoutputStream除了维护一个数据队列之外,还维护了一个确认队列(ack队列)ack队列中的数据包是管线中第一台DataNode收到数据包后会第一时间复制一份到ack队列

8、当一个数据包在管线中所有DataNode写入完成,就从ack队列中移除该数据包,表示该数据包已经成功写入所有的管线的DataNode中。

9、如果在数据写入期间,管线中的DataNode发生故障,则执行如下操作:

a、关闭管线,将ack队列中的所有数据包都添加会数据队列的最前端,确保故障节点下游的DataNode不会丢失任何一个数据包。

b、将管线中正常的DataNode组成一个新的管线,为新管线指定一个新的标志并将该标志发送给NameNode,以便故障DataNode在恢复后可以删除存储的部分数据。

c、将数据队列中的数据包继续写入新管线中。

d、在有后续的数据包则正常处理。

10、当客户端完成数据的传输,调用数据流的close()方法。该方法将数据队列中剩余数据包写入到管线中,并等待确认。

11、客户端收到所有DataNode的确认后,通知NameNode文件写完了。

12、NameNode已经知道文件有哪些块组成,在等待数据块完成最小量复制后,返回成功。

4.2 hdfs数据读流程

4.2.1基本流程

  • 1、client端读取HDFS文件,client调用文件系统对象DistributedFileSystem的open方法
  • 2、返回FSDataInputStream对象(对DFSInputStream的包装)
  • 3、构造DFSInputStream对象时,调用namenode的getBlockLocations方法,获得file的开始若干block(如blk1, blk2, blk3, blk4)的存储datanode(以下简称dn)列表;针对每个block的dn列表,会根据网络拓扑做排序,离client近的排在前;
  • 4、调用DFSInputStream的read方法,先读取blk1的数据,与client最近的datanode建立连接,读取数据
  • 5、读取完后,关闭与dn建立的流
  • 6、读取下一个block,如blk2的数据(重复步骤4、5、6)
  • 7、这一批block读取完后,再读取下一批block的数据(重复3、4、5、6、7)
  • 8、完成文件数据读取后,调用FSDataInputStream的close方法

4.2.2容错

  • 情况一:读取block过程中,client与datanode通信中断
  • client与存储此block的第二个datandoe建立连接,读取数据
  • 记录此有问题的datanode,不会再从它上读取数据
  • 情况二:client读取block,发现block数据有问题
  • client读取block数据时,同时会读取到block的校验和,若client针对读取过来的block数据,计算检验和,其值与读取过来的校验和不一样,说明block数据损坏
  • client从存储此block副本的其它datanode上读取block数据(也会计算校验和)
  • 同时,client会告知namenode此情况;

-----------------------------------------------------------------------------------------------------------------------------

1、首先客户端会通过自身的对象向NameNode发送通知,请求读取文件。

2、NameNode返回给客户端该文件的block副本存储在哪些DataNode上,并且这些DataNode根据他们与客户端的距离排序。

3、客户端的对象选择离自己最近的DataNode开始读取文件

4、如果离自己最近的DataNode发生故障,则读第二近的。并记录发生故障的DataNode,下次再有要读该DataNode的时候,直接跳过

5、读取完毕

这个设计一个重点是:namenode告知客户端每个block中最佳的datanode,并让客户端直接连到datanode检索数据。由于数据流分散在集群中的所有datanode,这样可以使HDFS可扩展到大量的并发客户端。同时,namenode只需要响应block位置的请求,无需响应数据请求,否则namenode会成为瓶颈

4.3 hdfs的HA和namenode主备切换

HA实现的两个核心要点:故障转移的实现和共享存储的实现

NameNode 主备切换主要由 ZKFailoverController(ZKFC)、HealthMonitor 和 ActiveStandbyElector 这 3 个组件来协同实现:

ZKFailoverController 作为 NameNode 机器上一个独立的进程启动 (在 hdfs 启动脚本之中的进程名为 zkfc),启动的时候会创建 HealthMonitor 和 ActiveStandbyElector 这两个主要的内部组件,ZKFC 在创建 HealthMonitor 和 ActiveStandbyElector 的同时,也会向 HealthMonitor 和 ActiveStandbyElector 注册相应的回调方法

HealthMonitor 主要负责检测 NameNode 的健康状态,如果检测到 NameNode 的状态发生变化,会回调 ZKFC的相应方法进行自动的主备选举。

ActiveStandbyElector 主要负责完成自动的主备选举,内部封装了 Zookeeper 的处理逻辑,一旦 Zookeeper 主备选举完成,会回调 ZKFC 的相应方法来进行 NameNode 的主备状态切换

HDFS 面试篇《一》_客户端_13

NameNode 实现主备切换的流程如上图,有以下几步:

HealthMonitor 初始化完成之后会启动内部的线程来定时调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法,对 NameNode 的健康状态进行检测

HealthMonitor 如果检测到 NameNode 的健康状态发生变化,会回调 ZKFC 注册的相应方法进行处理

如果 ZKFC 判断需要进行主备切换,会首先使用 ActiveStandbyElector 来进行自动的主备选举

ActiveStandbyElector 与 Zookeeper 进行交互完成自动的主备选举

ActiveStandbyElector 在主备选举完成后,会回调 ZKFC 的相应方法来通知当前的 NameNode 成为主 NameNode 或备 NameNode。

ZKFC调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法将 NameNode 转换为 Active 状态或 Standby 状态。

------------------------------------------------------------------------------------------------------------------------------

  • 对于HDFS ,NN存储元数据在内存中,并负责管理文件系统的命名空间和客户端对HDFS的读写请求。但是,如果只存在一个NN,一旦发生“单点故障”,会使整个系统失效。
  • 虽然有个SNN,但是它并不是NN的热备份
  • 因为SNN无法提供“热备份”功能,在NN故障时,无法立即切换到SNN对外提供服务,即HDFS处于停服状态。
  • HDFS2.x采用了HA(High Availability高可用)架构。
  • 在HA集群中,可设置两个NN,一个处于“活跃(Active)”状态,另一个处于“待命(Standby)”状态。
  • 由zookeeper确保一主一备
  • 处于Active状态的NN负责响应所有客户端的请求,处于Standby状态的NN作为热备份节点,保证与active的NN的元数据同步
  • Active节点发生故障时,zookeeper集群会发现此情况,通知Standby节点立即切换到活跃状态对外提供服务
  • 确保集群一直处于可用状态
  • 如何热备份元数据:
  • Standby NN是Active NN的“热备份”,因此Active NN的状态信息必须实时同步到StandbyNN。
  • 可借助一个共享存储系统来实现状态同步,如NFS(NetworkFile System)、QJM(Quorum Journal Manager)或者Zookeeper。
  • Active NN将更新数据写入到共享存储系统,Standby NN一直监听该系统,一旦发现有新的数据写入,就立即从公共存储系统中读取这些数据并加载到Standby NN自己内存中,从而保证元数据与Active NN状态一致。
  • 块报告:
  • NN保存了数据块到实际存储位置的映射信息,为了实现故障时的快速切换,必须保证StandbyNN中也包含最新的块映射信息
  • 因此需要给所有DN配置Active和Standby两个NN的地址,把块的位置和心跳信息同时发送到两个NN上。

4.4 hdfs的federation(联邦)模式

HDFS 面试篇《一》_客户端_14

4.4.1为什么需要联邦

虽然HDFS HA解决了“单点故障”问题,但HDFS在扩展性、整体性能和隔离性方面仍有问题

  • 系统扩展性方面,元数据存储在NN内存中,受限于内存上限(每个文件、目录、block占用约150字节)
  • 整体性能方面,吞吐量受单个NN的影响
  • 隔离性方面,一个程序可能会影响其他程序的运行,如果一个程序消耗过多资源会导致其他程序无法顺利运行
  • HDFS HA本质上还是单名称节点

4.4.2HDFS联邦可以解决以上三个问题

  • HDFS联邦中,设计了多个命名空间;每个命名空间有一个NN或一主一备两个NN,使得HDFS的命名服务能够水平扩展
  • 这些NN分别进行各自命名空间namespace和块的管理,相互独立,不需要彼此协调
  • 每个DN要向集群中所有的NN注册,并周期性的向所有NN发送心跳信息和块信息,报告自己的状态
  • HDFS联邦每个相互独立的NN对应一个独立的命名空间
  • 每一个命名空间管理属于自己的一组块,这些属于同一命名空间的块对应一个“块池”的概念。
  • 每个DN会为所有块池提供块的存储,块池中的各个块实际上是存储在不同DN中的

-------------------------------------------------------------------------------------------------------------------------------

namenode在内存中保存着文件系统中每个文件和每个数据块的引用关系,这意味着对于一个拥有大量文件的超大集群来说,内存将成为限制系统横向扩展的瓶颈。

2.x以后通过联邦模式允许系统通过添加namenode实现扩展,其中namenode管理文件系统命名空间的一部分,例如一个namenode可能管理/user目录下的所有文件,而另一个namenode可能管理/share目录下的所有文件。

该特性允许一个HDFS集群中存在多个NameNode同时对外提供服务,这些NameNode分管一部分目录(水平切分),彼此之间相互隔离,但共享底层的DataNode存储资源

4.5 hdfs优缺点

优点:

  • 适合存储大文件,能用来存储管理PB级的数据;不适合存储小文件(每个文件、目录、block占用大概150Byte字节的元数据;所以HDFS适合存储大文件,不适合存储小文件
  • 处理非结构化数据
  • 流式的访问数据,一次写入、多次读写
  • 运行于廉价的商用机器集群上,成本低
  • 高容错:故障时能继续运行且不让用户察觉到明显的中断
  • 可扩展

局限性:

  • 不适合处理低延迟数据访问
  • DFS是为了处理大型数据集分析任务的,主要是为达到高的数据吞吐量而设计的
  • 对于低延时的访问需求,HBase是更好的选择
  • 无法高效存储大量的小文件
  • 小文件会给Hadoop的扩展性和性能带来严重问题
  • 利用SequenceFile、MapFile等方式归档小文件
  • 不支持多用户写入及任意修改文件
  • 文件有一个写入者,只能执行追加操作
  • 不支持多个用户对同一文件的写操作,以及在文件任意位置进行修改

4.6 心跳机制

HDFS 面试篇《一》_数据_15

工作原理:

  1. NameNode启动的时候,会开一个ipc server在那里
  2. DataNode启动后向NameNode注册,每隔3秒钟向NameNode发送一个“心跳heartbeat
  3. 心跳返回结果带有NameNode给该DataNode的命令,如复制块数据到另一DataNode,或删除某个数据块
  4. 如果超过10分钟NameNode没有收到某个DataNode 的心跳,则认为该DataNode节点不可用
  5. DataNode周期性(6小时)的向NameNode上报当前DataNode上的块状态报告BlockReport;块状态报告包含了一个该 Datanode上所有数据块的列表

心跳的作用:

  1. 通过周期心跳,NameNode可以向DataNode返回指令
  2. 可以判断DataNode是否在线
  3. 通过BlockReport,NameNode能够知道各DataNode的存储情况,如磁盘利用率、块列表;跟负载均衡有关
  4. hadoop集群刚开始启动时,99.9%的block没有达到最小副本数(dfs.namenode.replication.min默认值为1),集群处于安全模式,涉及BlockReport;

心跳相关设置:

    在配置文件hdfs-default.xml中

4.7 负载均衡

  • 什么原因会有可能造成不均衡?
  • 机器与机器之间磁盘利用率不平衡是HDFS集群非常容易出现的情况
  • 尤其是在DataNode节点出现故障或在现有的集群上增添新的DataNode的时候
  • 为什么需要均衡?
  • 提升集群存储资源利用率
  • 从存储与计算两方面提高集群性能
  • 如何手动负载均衡?
$HADOOP_HOME/sbin/start-balancer.sh -t 5%	# 磁盘利用率最高的节点若比最少的节点,大于5%,触发均衡

4.8 文件压缩

4.8.1压缩算法

  • 文件压缩好处:
  • 减少数据所占用的磁盘空间
  • 加快数据在磁盘、网络上的IO
  • 常用压缩格式

压缩格式

UNIX工具

算 法

文件扩展名

可分割

压缩效率

压缩速度

DEFLATE

DEFLATE

.deflate

No



gzip

gzip

DEFLATE

.gz

No

中高

zip

zip

DEFLATE

.zip

YES



bzip

bzip2

bzip2

.bz2

YES

LZO

lzop

LZO

.lzo

Yes(if index)

Snappy

Snappy

.snappy

No

  • Hadoop的压缩实现类;均实现CompressionCodec接口

压缩格式

对应的编码/解码器

DEFLATE

org.apache.hadoop.io.compress.DefaultCodec

gzip

org.apache.hadoop.io.compress.GzipCodec

bzip2

org.apache.hadoop.io.compress.BZip2Codec

LZO

com.hadoop.compression.lzo.LzopCodec

Snappy

org.apache.hadoop.io.compress.SnappyCodec

  • 查看集群是否支持本地压缩(所有节点都要确认
[hadoop@node01 ~]$ hadoop checknative

HDFS 面试篇《一》_元数据_16

压缩比越高,压缩时间越长,压缩比:Snappy<LZ4<LZO<GZIP<BZIP2

hdfs压缩 https://blog.csdn.net/qq_38262266/article/details/79171524

4.9 小文件治理

4.9.1 HAR文件方案

本质启动mr程序,所以需要启动yarn

HDFS 面试篇《一》_元数据_17

用法:archive -archiveName <NAME>.har -p <parent path> [-r <replication factor>]<src>* <dest>

HDFS 面试篇《一》_元数据_18

HDFS 面试篇《一》_数据_19

# 创建archive文件;/testhar有两个子目录th1、th2;两个子目录中有若干文件,-r表示存档后设置3副本
hadoop archive -archiveName test.har -p /testhar -r 3 th1 th2 /outhar # 原文件还存在,需手动删除

# 查看archive文件
hdfs dfs -ls -R har:///outhar/test.har

# 解压archive文件
# 方式一
hdfs dfs -cp har:///outhar/test.har/th1 hdfs:/unarchivef # 顺序
hadoop fs -ls /unarchivef	
# 方式二
hadoop distcp har:///outhar/test.har/th1 hdfs:/unarchivef2 # 并行,启动MR

创建存档文件的问题:

1、存档文件的源文件目录以及源文件都不会自动删除需要手动删除

2、存档的过程实际是一个mapreduce过程,所以需要hadoop的mapreduce的支持

3、存档文件本身不支持压缩

4、存档文件一旦创建便不可修改,要想从中删除或者增加文件,必须重新建立存档文件

5、创建存档文件会创建原始文件的副本,所以至少需要有与存档文件容量相同的磁盘空间

4.9.2 Sequence Files方案

  • SequenceFile文件,主要由一条条record记录组成;每个record是键值对形式的
  • SequenceFile文件可以作为小文件的存储容器;
  • 每条record保存一个小文件的内容
  • 小文件名作为当前record的键;
  • 小文件的内容作为当前record的值;
  • 如10000个100KB的小文件,可以编写程序将这些文件放到一个SequenceFile文件。
  • 一个SequenceFile是可分割的,所以MapReduce可将文件切分成块,每一块独立操作。
  • 具体结构(如下图):
  • 一个SequenceFile首先有一个4字节的header(文件版本号)
  • 接着是若干record记录
  • 记录间会随机的插入一些同步点sync marker,用于方便定位到记录边界
  • 不像HAR,SequenceFile支持压缩。记录的结构取决于是否启动压缩
  • 支持两类压缩:
  • 不压缩NONE,如下图
  • 压缩RECORD,如下图
  • 压缩BLOCK,①一次性压缩多条记录;②每一个新块Block开始处都需要插入同步点;如下图
  • 在大多数情况下,以block(注意:指的是SequenceFile中的block)为单位进行压缩是最好的选择
  • 因为一个block包含多条记录,利用record间的相似性进行压缩,压缩效率更高
  • 把已有的数据转存为SequenceFile比较慢。比起先写小文件,再将小文件写入SequenceFile,一个更好的选择是直接将数据写入一个SequenceFile文件,省去小文件作为中间媒介.

HDFS 面试篇《一》_客户端_20

HDFS 面试篇《一》_元数据_21

创建sequence file的过程可以使用mapreduce工作方式完成

对于index,需要改进查找算法

对小文件的存取都比较自由,也不限制用户和文件的多少,但是该方法不能使用append方法,所以适合一次性写入大量小文件的场景

小文件治理:https://www.aboutyun.com/thread-14227-1-1.html

4.10 文件快照

4.10.1 什么是快照

  • 快照比较常见的应用场景是数据备份,以防一些用户错误或灾难恢复
  • 快照snapshots是HDFS文件系统的,只读的、某时间点的拷贝
  • 可以针对某个目录,或者整个文件系统做快照
  • 创建快照时,block块并不会被拷贝。快照文件中只是记录了block列表和文件大小,不会做任何数据拷贝

4.10.2 快照操作

允许快照

允许一个快照目录被创建。如果这个操作成功完成,这个目录就变成snapshottable

用法:hdfs dfsadmin -allowSnapshot <snapshotDir>

hdfs dfsadmin -allowSnapshot /wordcount
禁用快照

用法:hdfs dfsadmin -disallowSnapshot <snapshotDir>

hdfs dfsadmin -disallowSnapshot /wordcount
创建快照

用法:hdfs dfs -createSnapshot <snapshotDir> [<snapshotName>]

#注意:先将/wordcount目录变成允许快照的
hdfs dfs -createSnapshot /wordcount wcSnapshot
查看快照
hdfs dfs -ls /wordcount/.snapshot

HDFS 面试篇《一》_客户端_22

重命名快照

这个操作需要拥有snapshottabl目录所有者权限

用法:hdfs dfs -renameSnapshot <snapshotDir> <oldName> <newName>

hdfs dfs -renameSnapshot /wordcount wcSnapshot newWCSnapshot
用快照恢复误删除数据

HFDS的/wordcount目录,文件列表如下

HDFS 面试篇《一》_元数据_23

误删除/wordcount/edit.xml文件

hadoop fs -rm /wordcount/edit.xml

HDFS 面试篇《一》_数据_24

恢复数据

hadoop fs -cp /wordcount/.snapshot/newWCSnapshot/edit.xml /wordcount
删除快照

这个操作需要拥有snapshottabl目录所有者权限

用法:hdfs dfs -deleteSnapshot <snapshotDir> <snapshotName>

hdfs dfs -deleteSnapshot /wordcount newWCSnapshot

五、hdfs shell

5.1 hdfs与getconf结合使用

5.1.1 获取NameNode的节点名称(可能有多个)

hdfs getconf -namenodes

5.1.2 获取hdfs最小块信息

hdfs getconf -confKey dfs.namenode.fs-limits.min-block-size

5.1.3 查找hdfs的NameNode的RPC地址

hdfs getconf -nnRpcAddresses


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
GPYyDLfgzzIb