HDFS基础知识点总结
更多好文可微信搜索关注公众号:知了小巷
公众号后台回复 资料 ,可领取2020大数据学习大礼包
1. HDFS读写流程
写数据流程
- 客户端Client通过Distributed FileSystem模块向NameNode节点发出上传文件请求,NameNode检查目标文件是否已经存在以及父目录是否存在;
- NameNode返回是否可以上传,如果不能上传则返回异常。
- 确定可以上传,客户端请求第一个block上传到哪几个DataNode服务器上。
- NameNode返回3个DataNode节点(有两个副本、且遵循机架或数据中心感应原则),假定为dn1、dn2、dn3。
- 客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道(Pipeline of DataNodes)建立完成。
- dn1、dn2、dn3逐级应答客户端。
- 客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet(64KB)为单位,dn1收到一个packet就会传给dn2,dn2收到后传给dn3;dn1每传一个packet就会放入一个应答队列等待应答。
- 当一个block传输完成之后,客户端再次请求NameNode上传第二个block的服务器。(重复执行3~7步)
读数据流程
- 客户端Client首先调用FileSystem.open()方法,获取到DistributedFileSystem实例。
- DistributedFileSystem向NameNode发起RPC(远程过程调用)请求获取文件的开始部分或全部block列表,对于每个返回的块,都包含该块所在的DataNode地址。这些DataNode会按照Hadoop定义的集群拓扑结构得出客户端的距离,然后再进行排序。如果客户端本身就是一个DataNode,那么将从本地读取文件。
- DistributedFileSystem会向客户端Client返回一个支持文件定位的输入流对象FSDataInputStream,用于客户端读取数据。FSDataInputStream包含一个DFSInputStream对象,这个对象用来管理DataNode和NameNode之间的IO。
- 客户端调用read()方法,DFSInputStream就会找出距离客户端最近的DataNode并连接DataNode。
- DFSInputStream对象中包含文件开始部分的数据块所在的DataNode地址,首先它会连接包含文件第一个块最近的DataNode。随后,在数据流中重复调用read()方法,直到这个块全部读完为止。如果第一个block块的数据读完,就会关闭指向第一个block块的DataNode连接,接着读取下一个block块。
-
如果第一批block都读完了,DFSInputStream就会去NameNode拿下一批blocks的location,然后继续读,如果所有block块都读完,这时就会关闭掉所有的流。
需要注意的是:
read()方法是并行读取block数据,不是一块接着一块的读取;NameNode只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据。最终读取来所有的block会合并成一个完整的最终文件。
2. HDFS中NameNode和DataNode的作用?
NameNode
NameNode理解为Master-Slave架构中的Master,是集群管理者。NameNode是HDFS集群的元数据节点,集群中只能有一个Active的NameNode对外提供服务。
- 管理HDFS的名称空间(文件目录树):HDFS很方便的一点就是对于用户来说很友好,用户不需要考虑具体实现细节,看到的目录结构和使用的Linux或类Unix文件系统类似。
- 管理数据块block映射信息及副本信息;一个文件对应的块的名字以及块被存储在什么位置,还有每一个文件备份多少都是由NameNode来管理。
- 处理客户端读写请求。
DataNode
DataNode理解为Master-Slave架构中的Slave,是HDFS集群实际存储数据块的节点,NameNode下达命令,DataNode执行实际的数据读写操作。
- 存储实际的数据块。
- 执行数据块的读写操作。
3. SecondaryNameNode的作用?或者NameNode的启动过程?
SecondaryNameNode有两个作用,一是镜像备份;二是日志与镜像的定期合并,即合并NameNode的edit logs到fsimage文件中。
第一阶段 NameNode启动
- 第一次启动NameNode格式化后,创建fsimage和edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
- 客户端对元数据进行增删改的请求。
- NameNode记录操作日志,更新滚动日志。
- NameNode在内存中对数据进行增删改查。
第二阶段 SecondaryNameNode参与工作
SecondaryNameNode询问NameNode是否需要Checkpoint。直接带回NameNode是否要做Checkpoint的结果。
(Checkpoint的判断条件:① 定时时间到,默认1小时 ② edits中的操作次数已满,默认100万)
- SecondaryNameNode请求执行Checkpoint。
- NameNode滚动正在写的edits日志。
- 将滚动前的编辑日志和镜像文件拷贝到SecondaryNameNode。
- SecondaryNameNode加载编辑日志和镜像文件到内存,并进行合并。
- 生成新的镜像文件fsimage.chkpoint。
- 拷贝fsimage.chkpoint到NameNode。
-
NameNode将fsimage.chkpoint重新命名成fsimage。
注意:SecondaryNameNode不是NameNode的备份节点,NameNode挂了,SecondaryNameNode顶不上去的。
web端访问SecondaryNameNode
- 启动集群
浏览器中输入:http://xxxxx:50090/status.html
Hadoop3.x默认端口号是9868 - 页面可以查看SecondaryNameNode的信息
4. 什么情况下HDFS集群会进入安全模式?有哪些解决办法?
-
进入安全模式的情况:
集群启动时必定会进入安全模式:
需要注意:如果满足“最小副本条件”,NameNode会在30秒钟之后就退出安全模式。所谓的最小副本条件指的是在整个文件系统中99.9%的块满足最小副本级别(默认值:dfs.replication.min=1)。在启动一个刚刚格式化的HDFS集群时,因为系统中还没有任何块,所以NameNode不会进入安全模式。
NameNode启动时,首先将镜像文件fsimage载入内存,并执行编辑日志edits中的各项操作。一旦在内存中成功建立文件系统元数据的镜像,则创建一个新的fsimage文件和一个空的编辑日志。此时,NameNode开始监听DataNode请求。但是此刻,NameNode运行在安全模式,即NameNode的文件系统对于客户端来说是只读的。
HDFS系统中的数据块的位置并不是由NameNode维护的,而是以块列表的形式存储在DataNode中。在安全模式下,各个DataNode会向NameNode发送最新的块列表信息,NameNode了解到足够多的块位置信息之后,即可高效运行文件系统。 在系统的正常操作期间,NameNode会在内存中保留所有块位置的映射信息。 -
异常情况下导致的安全模式
原因:block数据块确实有缺失,当NameNode发现集群中的block数据块丢失数量达到一个阈值时,NameNode就会进入安全模式状态,不再接收客户端的数据更新操作。
解决办法
-
调低进入安全模式的阈值
hdfs-site.xml配置文件中:1
2<name>dfs.namenode.safemode.threshold-pct</name>
<value>0.999f</value> -
强制离开
1
hdfs dfsadmin-safemode leave
-
重新格式化集群
- 修复损坏的块文件
dfsadmin操作语法
集群处于安全模式下,不能执行重要操作(写操作)。集群启动完成后,自动退出安全模式。
查看安全模式下的状态
hdfs dfsadmin -safemode get
进入安全模式状态
hdfs dfsadmin -safemode enter
离开安全模式状态
hdfs dfsadmin -safemode leave
等待安全模式状态
hdfs dfsadmin -safemode wait
5. 为什么HDFS不适合存储小文件?
HDFS天生就是为存储大文件而生的,一个块的元数据大小大概在150字节左右,存储一个小文件就要占用NameNode 150字节的内存,如果存储大量的小文件,很快就会将NameNode的内存耗尽,而整个集群存储的数据量却很小,失去了HDFS的意义,同时也会影响NameNode的寻址时间,导致寻址时间过长。
可以将大量小文件预先合并后再上传,或者将文件以append的形式追加在HDFS文件末尾。
6. HDFS支持的存储格式和压缩算法?
-
存储格式
SequenceFile
SequenceFile是以二进制键值对的形式存储数据,支持三种记录存储方式:
无压缩:IO效率较差,和压缩相比,不压缩的情况下没有什么优势
记录级压缩:对每条记录都压缩,这种压缩效率比较一般
块级压缩:这里的块不同于HDFS中的块的概念,这种方式会将达到指定块大小的二进制数据压缩为一个块。Avro
将数据定义和数据一起存储在一条消息中,其中数据定义是以JSON格式进行存储,数据是以二进制格式存储。Avro标记用于将大型数据集分割成适合MapReduce处理的子数据集。RCFile
升级版ORC。以列格式保存每个行组数据。它不是存储第一行然后是第二行,而是存储所有行上的第一列,然后是所有行上的第二列,以此类推。Parquet
Parquet是Hadoop的一种列式存储格式,提供了高效的编码和压缩方案。 -
压缩算法
Gzip压缩
优点:压缩比率高,而且压缩/解压缩速度也比较块;Hadoop本身默认支持,在应用中处理Gzip格式的文件和直接处理普通文本一样;大部分Linux系统都自带gzip命令,使用比较方便。
缺点:不支持数据分片split。
应用场景:当每个文件压缩之后在130M以内的(一个块大小内),都可以考虑使用Gzip压缩格式。Bzip压缩
优点:支持split;具有很高压缩率,比Gzip压缩率还要高;Hadoop本身默认支持,但不支持Native;在Linux系统下自带bzip2命令,使用方便。
缺点:压缩/解压缩速度慢;不支持Native。
应用场景:适合对速度要求不高,但需要较高的压缩率的时候,可以作为MapReduce作业的输出格式;或者输出之后的数据比较大,处理之后的数据需要压缩存档,减少磁盘空间并且以后数据用得比较少的情况;或者对单个很大的文本文件想压缩减少存储空间,同时又支持split,而且兼容之前的应用程序(应用程序不需要改动)的情况。Lzo压缩
优点:压缩/解压缩速度也比较快,合理的压缩率;支持split,是Hadoop中最流行的压缩格式;可以在Linux系统下安装lzop命令,使用方便。
缺点:压缩率比Gzip要低一些;Hadoop本身不支持,需要安装。在应用中对lzo格式的文件需要做一些特殊处理(为了支持split需要创建索引,还需要指定inputformat为lzo格式)。
应用场景:一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越明显。Snappy压缩
优点:高压缩速度和合理的压缩率。
缺点:不支持split;压缩率比Gzip要低;Hadoop本身不支持,需要安装。
应用场景:当MapReduce作业的Map输出的数据比较大的时候,作为Map到Reduce的中间数据的压缩格式;或者作为一个MapReduce作业的输出和另外一个MapReduce作业的输入。
一般Lzo和Snappy用的比较多,Snappy不是CDH自带的。
7. HDFS的可靠性策略
-
文件完整性
- 在HDFS文件建立时,每个数据块都会产生校验和,校验和会保存在.meta文件里面。
- 客户端获取数据的时候可以检查校验和是否相同,从而发现数据块是否损坏。
- 如果正在读取的数据库损坏,则可以继续读取其它的副本数据。NameNode标记该块已经损坏,然后复制block达到预期设置的文件备份数。
- DataNode在其文件创建后三周验证其checksum。
-
网络或者机器失效
- 副本冗余。
- 机架感知策略(副本放置策略)。
- 心跳机制策略。
-
Active NameNode挂掉
- 主备切换(HA高可用,1个Active,1或多个Standby)
- 镜像文件和操作日志磁盘存储
- 镜像文件和操作日志可以存储多份,多磁盘存储(JournalNode)
-
其他保障可靠性机制
- 快照(保存了HDFS系统某一时刻的影像,可以还原到该时刻)
- 回收站机制。(.trash 重要!)
- 安全模式
8. HDFS的优缺点
-
HDFS优点
- 高容错性:数据自动保存多个副本,副本丢失以后,会自动恢复。
- 适合批处理:移动计算而非数据、把数据位置暴露给计算框架。
- 适合大规模数据处理:GB、TB、甚至PB级数据、百万规模以上的文件数量,1000以上节点规模。
- 流式文件访问:一次写入,多次读取;保证数据一致性。
- 可构建在廉价机器上:通过多副本提高可靠性,提供了容错和恢复机制。
-
HDFS缺点
- 不适合低延迟数据访问:比如毫秒级、低延迟与高吞吐率。
- 不适合小文件存取:占用NameNode大量内存,寻道时间超过读取时间。
- 不适合并发写入、文件随机修改;一个文件只能有一个写者,仅支持append。
9. DataNode宕机后,集群能否立即下线DataNode?DataNode下线之后,集群会做哪些工作?
不能立即下线,默认需要等待10分30秒。
DataNode下线之后,集群会复制下线的DataNode管理的数据块。
10. 重新格式化NameNode以后,使用start-dfs.sh启动集群,DataNode能正常启动吗?为什么?
不能,NameNode重新格式化之后,clusterid发生改变,而DataNode节点还保存着原来的clusterid。
11. DataNode在什么情况下不会备份?
DataNode在强制关闭或者非正常断电的情况下不会备份。
12. 集群中其中一个DataNode出现错误会怎么样?
这个出错的DataNode管理的数据会在其他正常DataNode上重新做备份。
13. 一个DataNode宕机了,怎会恢复?
将DataNode节点的数据删除,重新当成新节点加入集群即可。
HDFS cluster primarily consists of a NameNode that manages the file system Metadata and a DataNodes that stores the actual data.
附:HDFS写数据流程图12步
- A client initiates write operation by calling ‘create()’ method of DistributedFileSystem object which creates a new file - Step no. 1 in the above diagram.
- DistributedFileSystem object connects to the NameNode using RPC call and initiates new file creation. However, this file creates operation does not associate any blocks with the file. It is the responsibility of NameNode to verify that the file (which is being created) does not exist already and a client has correct permissions to create a new file. If a file already exists or client does not have sufficient permission to create a new file, then IOException is thrown to the client. Otherwise, the operation succeeds and a new record for the file is created by the NameNode.
- Once a new record in NameNode is created, an object of type FSDataOutputStream is returned to the client. A client uses it to write data into the HDFS. Data write method is invoked (step 3 in the diagram).
- FSDataOutputStream contains DFSOutputStream object which looks after communication with DataNodes and NameNode. While the client continues writing data, DFSOutputStream continues creating packets with this data. These packets are enqueued into a queue which is called as DataQueue.
- There is one more component called DataStreamer which consumes this DataQueue. DataStreamer also asks NameNode for allocation of new blocks thereby picking desirable DataNodes to be used for replication.
- Now, the process of replication starts by creating a pipeline using DataNodes. In our case, we have chosen a replication level of 3 and hence there are 3 DataNodes in the pipeline.
- The DataStreamer pours packets into the first DataNode in the pipeline.
- Every DataNode in a pipeline stores packet received by it and forwards the same to the second DataNode in a pipeline.
- Another queue, ‘Ack Queue’ is maintained by DFSOutputStream to store packets which are waiting for acknowledgment from DataNodes.
- Once acknowledgment for a packet in the queue is received from all DataNodes in the pipeline, it is removed from the ‘Ack Queue’. In the event of any DataNode failure, packets from this queue are used to reinitiate the operation.
- After a client is done with the writing data, it calls a close() method (Step 9 in the diagram) Call to close(), results into flushing remaining data packets to the pipeline followed by waiting for acknowledgment.
- Once a final acknowledgment is received, NameNode is contacted to tell it that the file write operation is complete.
附:HDFS读数据流程图7步
- A client initiates read request by calling ‘open()’ method of FileSystem object; it is an object of type DistributedFileSystem.
- This object connects to namenode using RPC and gets metadata information such as the locations of the blocks of the file. Please note that these addresses are of first few blocks of a file.
- In response to this metadata request, addresses of the DataNodes having a copy of that block is returned back.
- Once addresses of DataNodes are received, an object of type FSDataInputStream is returned to the client. FSDataInputStream contains DFSInputStream which takes care of interactions with DataNode and NameNode. In step 4 shown in the above diagram, a client invokes ‘read()’ method which causes DFSInputStream to establish a connection with the first DataNode with the first block of a file.
- Data is read in the form of streams wherein client invokes ‘read()’ method repeatedly. This process of read() operation continues till it reaches the end of block.
- Once the end of a block is reached, DFSInputStream closes the connection and moves on to locate the next DataNode for the next block
- Once a client has done with the reading, it calls a close() method.