HDFS面试重点
小伙伴们大家好,今天这篇文章来聊下面试中会重点问到的HDFS问题。
之前介绍过HDFS是Hadoop的组成,是分布式文件管理系统,负责解决大数据的存储问题。面试中问到最多的就是HDFS的读写流程和HDFS各组成的工作机制。
1、HDFS的读写流程
1.1、读数据流程
- 客户端通过Distributed FileSystem向NameNode请求下载文件。
- NameNode通过查询元数据,找到文件块所在的DataNode地址,返回目标文件的元数据。
- 挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
- DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
- 客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。
1.2、写数据流程
- 客户端通过Distributed FileSystem向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。
- NameNode返回是否可以上传。
- 客户端请求第一个Block上传到哪几个DataNode服务器上。
- NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。
- 客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
- dn1、dn2、dn3逐级应答客户端。
- 客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3,dn1每传一个packet会放入一个应答队列等待应答。
- 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器(重复执行3-7步)。
2、NameNode和SecondaryNameNode
2.1、工作机制
思考:大家都知道NameNode是存储文件元数据的,但是NameNode的元数据存储在哪里?
不妨来假设一下,如果存储在NameNode节点的磁盘中,因为频繁访问会导致效率过低,因此需要放到内存中,但一旦断电元数据又会丢失。针对这些情况,产生了在磁盘中备份元数据的FsImage。
思考:那么又有了新的问题,什么时候更新FsImage?
如果内存中的元数据更新时同时更新FsImage会导致效率过低,但不更新一旦断电会丢失数据,导致一致性问题。因此,引入Edits文件(只进行追加操作),每当元数据有更新或添加元数据时,修改内存中的元数据并追加到Edits中。这样即使断电也可以通过FsImage和Edits的合并来合成完整的元数据。
思考:但是长时间添加数据到Edits又会导致该文件过大,访问效率降低,且断电后恢复元数据时间过长。
因此需要定期进行FsImage和Edits的合并,如果由NameNode节点完成过于繁忙,此时引入一个新的节点SecondaryNameNode,专门用于FsImage和Edits的合并。
工作机制:
第一阶段:NameNode启动并工作
- 第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
- 客户端对元数据进行增删改的请求。
- NameNode记录操作日志,更新滚动日志。
- NameNode在内存中对元数据进行增删改。
第二阶段:SecondaryNameNode工作
- SecondaryNameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否CheckPoint结果。
- SecondaryNameNode请求执行CheckPoint。
- NameNode滚动正在写的Edits日志。
- 将滚动前的编辑日志和镜像文件拷贝到SecondaryNameNode。
- SecondaryNameNode加载编辑日志和镜像文件到内存并合并。
- 生成新的镜像文件fsimage.chkpoint。
- 拷贝fsimage.chkpoint到NameNode。
- NameNode将fsimage.chkpoint重新命名成fsimage。
2.2、Fsimage和Edits解析
在NameNode被格式化之后,将会在hadoop安装目录下的data/tmp/dfs/name/current这个路径中产生四个文件,分别是fsimage_0000000000000000000、fsimage_0000000000000000000.md5、seen_txid、VERSION四个文件。
fsiamge文件:HDFS文件系统中元数据的一个永久性的检查点,包含HDFS文件系统的所有目录和文件inode的序列化信息。
edits文件:存放HDFS文件系统的所有更新操作的路径,客户端执行的所有写操作首先会被记录到edits文件中。
seen_txid文件:保存的是一个数字,是最后一个edits_的数字。
每次NameNode启动的时候都会将fsimage文件读入内存,加载edits里面的更新操作,保证内存中元数据是最新的,可以看成NameNode启动的时候就将fsimage和edits进行了合并。
查看fsimage文件:
# hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径
hdfs oiv -p XML -i fsimage_0000000000000000019 -o /data/fsimage.xml
cat /data/fsimage.xml
注:查看fsimage后发现并没有记录块所对应的DataNode,因为在集群启动后,要求DataNode上报数据块信息,并间隔一段时间后再次上报。
查看edits文件:
# hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
hdfs oev -p XML -i edits_0000000000000000020-0000000000000000020 -o /data/edits.xml
cat /data/edits.xml
2.3、CheckPoint时间设置
通常情况下,SecondaryNameNode每隔一小时执行一次。
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
<description>每隔3600秒2NN执行一次</description>
</property>
<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
<description>操作次数达到1000000次2NN执行一次</description>
</property>
<property>
<name>dfs.namenode.checkpoint.check.period</name>
<value>60</value>
<description>1分钟检查一次</description>
</property>
2.4、NameNode故障处理
NameNode故障后可以使用两种方法恢复数据。
- 手动将SecondaryNameNode中数据拷贝到NameNode存储数据的目录。
kill -9 xxx # kill掉NameNode进程
rm -rf hadoop/data/tmp/dfs/name/* # 删除NameNode存储的数据
scp -r dgf@hadoop3:/hadoop/data/tmp/dfs/namesecondary/* ./name/ # 拷贝SecondaryNameNode中数据到原NameNode存储数据目录
hdfs --daemon start namenode # 重新启动NameNode
- 使用-importCheckpoint选项启动NameNode守护进程,将SecondaryNameNode中数据拷贝到NameNode目录中。
- 修改hdfs-site.xml配置文件:
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>120</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/hadoop/data/tmp/dfs/name</value>
</property>
- kill -9 NameNode进程
- 删除NameNode存储的数据
- 如果SecondaryNameNode和NameNode不在同一个节点上,需要将SecondaryNameNode存储数据的目录拷贝到NameNode存储数据的平级目录,并删除in_use.lock文件
- 导入检查点数据(等一会用ctrl+c结束掉)
bin/hdfs namenode -importCheckpoint
- 启动NameNode
hdfs --daemon start namenode
2.5、集群安全模式
NameNode启动时,先将镜像文件fsimage载入内存,并执行编辑日志edits中的各项操作,在内存中成功建立元数据的映像后,则创建一个新的fsimage文件和一个空的编辑日志。此时NameNode开始监听DataNode请求。这个过程中NameNode一直运行在安全模式中(客户端只读不可写)。
DataNode启动后,在正常操作期间,NameNode会在内存中保留所有块位置的映射信息;在安全模式下,各个DataNode会向NameNode发送最新的块列表信息。系统中的数据块的位置并不是由NameNode维护的,而是以块列表的形式存储在DataNode中。
安全模式退出判断:如果满足最小副本条件,NameNode会在30s后退出安全模式。最小副本条件是指文件系统中99.9%的块满足最小副本级别(默认值为1)。当然在启动刚格式化的集群时虽然没有块也不会进入安全模式。
安全模式相关命令:
bin/hdfs dfsadmin -safemode get # 查看安全模式状态
bin/hdfs dfsadmin -safemode enter # 进入安全模式
bin/hdfs dfsadmin -safemode leave # 离开安全模式
bin/hdfs dfsadmin -safemode wait # 等待安全模式状态
3、DataNode
3.1、工作机制
- 一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
- DataNode启动后向NameNode注册,通过后周期性(1小时)的向NameNode上报所有块信息。
- 心跳是3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。
- 集群运行中可以安全加入和退出一些机器。
3.2、数据完整性
DataNode节点保证数据完整性的方法:
- 当DataNode读取block时,会计算checksum。
- 如果计算后的checksum与block创建时值不一致,说明block已经损坏。
- client读取其他DataNode上的block。
- DataNode在其文件创建后周期验证checksum。
3.3、掉线时限参数设置
如果DataNode进程死亡或网络故障造成DataNode无法与NameNode通信,NameNode不会立即判定节点死亡,要经过一段时间,先命名为超时时长。
如果定义超时时间为TimeOut,则超时时长的计算公式为:
TimeOut=2*dfs.namenode.heartbeat.recheck-interval+10*dfs.heartbeat.interval
。
默认的dfs.namenode.heartbeat.recheck-interval为5分钟,默认的dfs.heartbeat.interval为3秒。
注:hdfs-site.xml配置文件中dfs.namenode.heartbeat.recheck-interval的单位是毫秒,dfs.heartbeat.interval的单位是秒。
3.4、服役新数据节点
如果公司数据量增大,需要添加新节点,可以用下面的步骤添加。
- 新服务器安装好系统配置好IP和主机名等准备工作后,发送hadoop到新服务器,然后删除data和logs目录并修改配置文件,最后source一下配置文件。
- 直接启动新节点即可关联到集群
hdfs --daemon start datanode,sbin/yarn-daemon.sh start nodemanager
。 - 如果数据不均衡,可以用
./sbin/start-balancer.sh
命令实现集群的再平衡。
3.5、退役旧数据节点
有两种方式可以退役旧节点,通过删除白名单或添加黑名单。
- 白名单,不在白名单上的节点会被退出。
touch dfs.hosts # 在hadoop安装目录下的/etc/hadoop路径下创建dfs.hosts文件,并添加主机名(退役节点除外)
# 在hdfs-site.xml配置文件中添加dfs.hosts属性并重启NameNode
# 分发配置文件
hdfs dfsadmin -refreshNodes # 刷新NameNode
yarn rmadmin -refreshNodes # 更新ResourceManager节点
./sbin/start-balancer.sh # 数据不均衡时用
- 黑名单,在黑名单上的节点会被强制退出。
touch dfs.hosts.exclude # 在hadoop安装目录下的/etc/hadoop路径下创建dfs.hosts.exclude文件,并添加退役节点主机名
# 在hdfs-site.xml配置文件中添加dfs.hosts.exclude属性并重启NameNode
hdfs dfsadmin -refreshNodes # 刷新NameNode
yarn rmadmin -refreshNodes # 更新ResourceManager节点
# 检查web页面,等待退役节点状态为decommissioned(所有块已复制完成),停止该节点及节点资源管理器。但是如果副本数是3且服役的节点小于等于3是不能退役成功的。
./sbin/start-balancer.sh # 数据不均衡时用
3.6、DataNode多目录配置
DataNode也可配置成多个目录,每个目录存储的数据不一样。
修改hdfs-site.xml配置文件:
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value>
</property>
今天的内容分享就到这里,下篇见。