HDFS原理剖析
前言
在上一章讲述了Hadoop的基础架构以及所担负的功能,这一章深入剖析背后的基本原理
疑问
依旧首先是提出几个问题,带着问题去思考HDFS底层架构
- HDFS是一个分布式结构,节点间如何沟通,如何判断节点挂了?
- HDFS重要的功能就是读写,具体的流程是什么?这也是面试常考的点
- 节点挂了是如何恢复的?
HDFS核心
心跳机制
- 什么是心跳机制?
- 简而言之心跳机制就等于员工定时向领导汇报
- 为什么需要心跳机制?
- 因为Master需要分配任务给slave,但需要确定slave是否正常工作
- HDFS如何实现?
- Master启动Server服务,等待slave连接
- slave启动就会自动连接Master,间隔时间为3s
- Namenode通过心跳机制得知Master状态,ResourceManager通过心跳得知NodeManager动态
- Master长时间没收到slave,就默认slave挂了
- 时长如何确定?
- 10min 30s,它是这样确定的,首先datanode正常情况下每隔3s向namenode汇报,连续10次没有汇报,namenode就认为datanode挂了,但是不能确认,启动确认机制,每间隔5Min向datanode发送一次检查,一次没有收到再发一次,还是没有响应的话就判断datanode死亡
- 如何修改设置
<property>
<name>dfs.namenode.heartbeat.recheck-interval</name>
<value>300000</value>
<description>This time decides the interval to check for expired datanodes.With this value and dfs.heartbeat.interval, the interval of deciding the datanode id stale ot not is also calculated. The unit of this configuration is millisecond. </description>
</property>
安全模式
两种情况
-
Namenode启动时会自动进入安全模式,表现就是可读不可写
- 原因:思考一下启动Namenode时,元数据信息从哪里加载?当然是磁盘+编辑日志edit,但是当启动时候,磁盘镜像中并不包含block 所在datanode信息,namenode无法加载到datanode信息,误认为datanode所有block丢失,从而进入安全模式,不允许写数据,而当slave启动后向namenode汇报所在信息后,namenode内存元数据就会存储到block所在信息
- 当满足最小副本数的时候,最小副本指的是整个文件系统中99.99%的块满足最小副本级别,Namenode就会在30s之后退出安全模式
-
Namenode发现集群中的block丢失到一定比例,默认0.1%,会自动进入安全模式
- 丢失率设置 dfs.namenode.safemode.threshold.pct = 0.999f
-
如何退出安全模式?
- 修复宕机的datanode
- 强制退出,造成数据丢失
-
语法
hdfs dfsadmin -safemode leave //强制NameNode退出安全模式
hdfs dfsadmin -safemode enter //进入安全模式
hdfs dfsadmin -safemode get //查看安全模式状态
hdfs dfsadmin -safemode wait //等待,一直到安全模式结束
副本存放
可以看到,副本放置策略为 同机器不同节点 不同机器不同节点
这样设计实际上是一种中合选择,三节点放在不同机器,跨节点写入代价高,放在同一机器没有效果,要挂都挂
副本数修改 修改hdfs.site文件
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Uzmv1SD-1595745048163)(C:\Users\86135\Desktop\捕获1.PNG)]
负载均衡问题
向HDFS写入数据的时候,Namenode会选择距离最近的DataNode接受数据,也就是客户端节点,这样一来就有一个问题,大家都往一个DataNode写数据势必会造成热点问题,HDFS提供了负载均衡操作。值得注意的是负载均衡广泛存在在大数据组件中
如何解决?sbin/start-balance.sh脚本可以做到负载聚恒
- sbin/start-balance.sh -t 10% 表示最高机器和最低机器差值不超过10%
自平衡速度很慢,原因是HDFS集群默认不允许balance操作占用很大的带宽,所以需要调整,hdfs-site文件修改
<property>
<name>dfs.balance.bandwidthPerSec</name>
<value>10485760</value>
<description> Specifies the maximum bandwidth that each datanode can utilize for the balancing purpose in term of the number of bytes per second. </description> </property>
HDFS读写流程
写流程
这个容易面试考 ,八股流程
一句话描述:hdfs client找namenode要datanode地址,找到了就写入到datanode,datanode写完一个要往备份写,备份写完才算完成,才会给client反馈写入成功指令
详细流程:
1、客户端通过调用 DistributedFileSystem 的 create 方法,创建一个新的文件。
2、DistributedFileSystem 通过 RPC(远程过程调用)调用 NameNode,去创建一个没有 blocks 关联
的新文件。创建前,NameNode 会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果
校验通过,NameNode 就会记录下新文件,否则就会抛出IO异常。3、前两步结束后会返回 FSDataOutputStream 的对象,和读文件的时候相似,FSDataOutputStream
被封装成 DFSOutputStream,DFSOutputStream 可以协调 NameNode 和 DataNode。客户端开始写
数据到DFSOutputStream,DFSOutputStream 会把数据切成一个个小 packet,然后排成队列 data
queue。
4、DataStreamer 会去处理接受 data queue,它先问询 NameNode 这个新的 block 最适合存储的在
哪几个DataNode里,比如重复数是3,那么就找到3个最适合的 DataNode,把它们排成一个
pipeline。DataStreamer 把 packet 按队列输出到管道的第一个 DataNode 中,第一个 DataNode 又
把 packet 输出到第二个 DataNode 中,以此类推。
5、DFSOutputStream 还有一个队列叫 ack queue,也是由 packet 组成,等待 DataNode 的收到响
应,当pipeline 中的所有 DataNode都表示已经收到的时候,这时 ack queue才会把对应的 packet 包
移除掉。
6、客户端完成写数据后,调用 close 方法关闭写入流。
7、DataStreamer 把剩余的包都刷到 pipeline 里,然后等待 ack 信息,收到最后一个ack 后,通知
DataNode 把文件标示为已完成。
读数据
一句话概括,不同的是返回给client的是一批datanode
1、客户端首先调用 FileSystem 对象的 open 方法打开文件,其实获取的是一个
DistributedFileSystem 的实例。
2、DistributedFileSystem 通过调用 RPC (远程过程调用)向 namenode 发起请求,获得文件的第一批
block 的位置信息。同一 block 按照备份数会返回多个 DataNode 的位置信息,并根据集群的网络拓扑
结构排序,距离客户端近的排在前面, 如果客户端本身就是该 DataNode,那么它将从本地读取文件。
3、DistributedFileSystem 类返回一个 FSDataInputStream 对象给客户端,用来读取数据,该对象会
被封装成 DFSInputStream 对象,该 DFSInputStream 对象管理着 datanode 和 namenode 的 I/O 数
据流。客户端对输入端调用 read 方法,DFSInputStream 就会找出离客户端最近的 datanode 并连接
datanode。
4、在数据流中重复调用 read() 函数,直到这个块全部读完为止。DFSInputStream 关闭和此
DataNode 的连接。接着读取下一个 block 块。这些操作对客户端来说是透明的,从客户端的角度来看
只是读一个持续不断的流。每读取完一个 block 都会进行 checksum 验证,如果读取 datanode 时出现
错误,客户端会通知 NameNode,然后再从下一个拥有该 block 拷贝的 datanode 继续读。
5、当正确读取完当前 block 的数据后,关闭当前的 DataNode 链接,并为读取下一个 block 寻找最佳
的DataNode。如果第一批 block 都读完了,且文件读取还没有结束,DFSInputStream 就会去
namenode 拿下一批 block 的位置信息继续读。
6、当客户端读取完毕数据的时候,调用 FSDataInputStream 的 close 方法关闭掉所有的流。
Namenode原理
用途 职责 流程
职责
- 负责client的请求
- 管理元数据
- 配置副本存放策略
- 解决负载均衡问题
元数据存取机制
namenode中的元数据存在磁盘和内存中,有一个显著问题就是没来得及写磁盘怎么办?这就出现了edits操作日志
流程:操作先写到edits文件中,再写道内存中,定期刷到磁盘中
如何 查看元数据?
- 查看hdfs.site文件,看自己的namenode数据指定目录在哪
- 进入namenode目录,可以看到数据有fsimage镜像和edits操作日志
seen_txid保存的是一个数字
version存放的是HDFS集群的版本信息
查看edits信息
命令:因为fsimage存储的是序列化信息,所以需要反序列化
查看fsimage信息
DataNode机制
职责
存数据,汇报信息,执行读写请求
掉线时长判断:上面已经讲过,不再赘述
SecondarhNamenode工作机制
分担namenode压力,主要执行的是fsimage+edits日志的合并工作
注意;并不能完全代替Namenode
sn主要做的就是checkpoint工作
流程:
-
通常情况下,sn隔一小时执行一次checkpoint,可通过hdfs.default文件设置 或者操作次数达到100w
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>
-
首先SN发送请求给NN,获取fsimage和edits文件
-
nn收到请求后,就舍弃了edits文件,创建一个新的edits文件写
-
NN发送给SN后,SN开始将fsimage加载到内存中,合并edits文件,并生成新的镜像fsimage.ckpt
-
SN发送给NN,NN会用此替换之前的fsimage,并将edits.new重命名为edits文件
client
作用:
- 切块呀,将文件切成block
- 与namenode交互获取文件位置,与datanode交互,上传下载文件
- 提一点,读文件的时候,client内部应该有缓存,这样就不需要每次都去请求nn获取datanode地址