HDFS中,NameNode负责管理元数据(DataNode),DataNode负责管理数据,为了及时确认每个DataNode是否在工作,DataNode每隔3秒,会向NameNode发送一个心跳报告,告知NameNode自己的存活情况和可用空间。在默认的情况下这个间隔就是3秒,也可以通过修改配置文件中的dfs.heartbeat.interval属性的值来调整间隔。
dfs.heartbeat.interval
3
Determines datanode heartbeat interval in seconds.
NameNode硬盘上存储的元数据包含三部分内容
NameNode的内存中存储的是进行读写操作时候的元数据,在操作开始的时候,内存中只包含抽象目录树、数据和块的对应关系,不包含数据块的存储位置,数据块的具体位置从DataNode发送的心跳报告中获取。
心跳机制是判断一个DataNode是否可用的依据。默认情况下,连续10次心跳报告接收不到的话,NameNode就会判断该DataNode可能当宕机了。连续的次数可以通过修改dfs.namenode.handler.count属性的值进行自定义。
dfs.namenode.handler.count
10
The number of server threads for the namenode.
NameNode判断DataNode可能宕机之后,会主动向DataNode发送检查请求,此时NameNode会开启后台的阻塞(守护)进程,并等待检查结果。默认的等待时间为5分钟,而这个时间同样也可以通过修改dfs.namenode.heartbeat.recheck-interval属性进行自定义。
dfs.namenode.heartbeat.recheck-interval
300000
This time decides the interval to check for expired datanodes.
With this value and dfs.heartbeat.interval, the interval of
deciding the datanode is stale or not is also calculated.
The unit of this configuration is millisecond.
这样检查的行为,默认是检查两次,只有当两次均无反应的情况下,才宣布该DataNode宕机。
经过上述过程可以判断,默认情况下,NameNode确定DataNode是否宕机最快需要630秒时间。
10次心跳报告==》103
5分钟的检查等待共两次==》560*2
共计630秒
机架策略又称副本存放策略,决定hdfs中每一个数据块的多个副本如何存储。默认情况下每一个块hdfs会创建3个副本。副本会有限存放到不属于同一个机机房的节点上,其次是不同机架,最后才是不同节点。
所谓的负载均衡,就是在Hadoop集群中,会尽可能的保证每一个DotaNode的存储空间使用率相近。NameNode会定期检查集群的负载,当发现DataNode某些节点的负载不均衡的时候回自动启动负载均衡。所谓的负载均衡就是将存储占比大 的DataNode节点上的数据移动到存储占比小的DataNoe节点上去。这个数据移动的过程是通过网络传输。默认的传输带宽是1M,以通过修改dfs.datanode.balance.bandwidthPerSec属性的值指定传输带宽。
dfs.datanode.balance.bandwidthPerSec
1048576
Specifies the maximum amount of bandwidth that each datanode
can utilize for the balancing purpose in term of
the number of bytes per second.
很多情况下,例如:当集群中节点很多的时候,系统自带的负载均衡达不到要求。此时需要手动启动负载均衡,执行
start-balancer.sh -t 10%
这个命令不会马上执行,有点类似于JVM的内存回收策略,提醒集群空闲的时候立即执行,加快数据传输的效率。命令后面的-t参数用于指定负载的停止条件,最后的10%表示,存储空间使用率最高和最低的两个DataNode的存储空间使用率差的绝对值小于等于10%时,负载均衡才会停止。执行这个脚本的时候一定要配合带宽的调整,不然就失去了手动调整的意义。
安全模式是集群的一种自我保护的模式,在这个模式下所有元数据发生改变的操作例如 put、mkdir、touchz、rm等都不能执行,只能执行ls、get、vat、tail等查询操作。
1)集群启动过程中进入安全模式
集群的启动顺序:NameNode-------->DataNode--------->SecondaryNameNode
Hints:SecondaryNameNode并不是NameNode的备份,详细分工可以看这篇Blog:https://www.cnblogs.com/chenyaling/p/5521464.html
a)NameNode启动时,会将NameNode硬盘中的元数据信息加载到内存中
b)DataNode启动成功就会向NameNode发送心跳报告和块报告,namenode接受datanode的心跳报告 ,统计块报告,添加上块的每一个副本的存储节点块的存储位置
c)SecondaryNameNode启动成功也会向NameNode发送心跳报告
集群在执行a、b步骤的时候元数据还没加载完成,此时无法对外提供服务,处于自我保护状态,就是安全模式
2)集群运行过程中进入安全模式的集中情况(以下条件满足任意一条就进入安全模式)
dfs.namenode.replication.min
1
Minimal block replication.
dfs.namenode.safemode.threshold-pct
0.999f
Specifies the percentage of blocks that should satisfy
the minimal replication requirement defined by dfs.namenode.replication.min.
Values less than or equal to 0 mean not to wait for any particular
percentage of blocks before exiting safemode.
Values greater than 1 will make safe mode permanent.
dfs.namenode.safemode.min.datanodes
0
Specifies the number of datanodes that must be considered alive
before the name node exits safemode.
Values less than or equal to 0 mean not to take the number of live
datanodes into account when deciding whether to remain in safe mode
during startup.
Values greater than the number of datanodes in the cluster
will make safe mode permanent.
dfs.namenode.safemode.extension
30000
Determines extension of safe mode in milliseconds
after the threshold level is reached.
dfs.namenode.resource.du.reserved
104857600
The amount of space to reserve/require for a NameNode storage directory
in bytes. The default is 100MB.
3)安全模式的离开条件(四个条件同时满足的时候才会离开安全模式)
dfs.namenode.name.dir
/home/hadoop/data/hadoopdata/name
namenode相关数据的存储目录
4)手动进入安全模式
当Hadoop集群升级的时候,通常会手动进入安全模式,方便集群维护
获取集群当前安全模式状态
hdfs dfsadmin -safemode get
进入安全模式
hdfs dfsadmin -safemode enter
离开安全模式
hdfs dfsadmin -safemode leave
等待安全模式
hdfs dfsadmin -safemode wait
文件读取的过程中如果发现某一个数据块的节点有故障,该故障节点会被报告给NameNode,NameNode会做出标识,下次再请求下载这个数据块的时候不会优先返回这个节点,而客户端会立即从其他储存这个数据块的节点重新读取。
文件首先会被进行逻辑切块:
只是范围的划分,并没有真正的切分
将数据的每一个数据块对应的数据偏移量范围划分出来
再进行物理切块:
将需要上传的数据 按照逻辑切块的区域划分 进行真正的切块
客户端每一个数据块上传的通道 pipline
客户端进行文件上传的时候单位:
dfs.client-write-packet-size
65536
Packet size for clients to write
文件上传中的问题:
以packet为单位数据 用数据队列缓存文件 数据通过pipline发送datanode
1)进行数据传输过程中或者构建pipline的过程中,出现某一个datanode宕机了,立即重试一次,发现仍然通信有问题,将这个有问题的datanode剔除出pipline,重新构建一个新的pipline 客户端—》第一个副本节点—》第三个副本的节点
客户端—》第一个副本节点—》第二个副本节点—》第三个副本的节点
2)整个文件上传过程中 只保证每一个数据块1个副本成功就认为成功
dfs.namenode.replication.min
1
Minimal block replication.
没有达到设置的副本的其他的副本,进行重新向namenode申请节点,namenode重新分配节点,异步复制的
3)所以我们进行分配每一个数据块节点的时候 第一个副本放在客户端所在节点 相当于本地拷贝 最大程度的保证至少一个副本上传成功
解析元数据磁盘存储的文件:
元数据存储路径
dfs.namenode.name.dir
/home/hadoop/data/hadoopdata/name
namenode相关数据的存储目录
路径:cd /home/hadoop/data/hadoopdata/name/current
元数据的磁盘存储文件解析:
edits_0000000000000000001-0000000000000000002
edits_inprogress_0000000000000000255
fsimage_0000000000000000254
fsimage_0000000000000000254.md5
seen_txid
VERSION
文件分为5类型:
1)edits_**** 历史日志文件 记录的是元数据的所有执行的操作日志
hadoop fs -mkdir /aa/ss
edits_**** 文件中就会记录一条日志数据 hadoop 16:34 mkdir /aa/ss
记录操作
2)edits_inprogress_0000000000000000255 正在编辑的日志文件
目前正在接受客户端写元数据请求的文件
3)fsimage_0000000000000000254 镜像文件 真正的元数据文件
内存中元数据的一个镜像
只包含一部分的元数据
fsimage_0000000000000000254.md5 镜像文件的加密
4)seen_txid id记录点
记录目前日志文件的最大编号
5)VERSION 版本信息 记录集群版本信息的
元数据写入的过程:
请求中需要修改元数据的时候 写入
hadoop fs -mkdir|put|rm|touchz …
1)先将元数据写入到内存中
内存的元数据永远是最新的 最全的元数据信息
2)将元数据的操作日志写入到磁盘中edits_inprogress*文件
磁盘中的 fsimage文件 不是最新的 和内存中的有偏差的
每隔一段时间,磁盘中的 fsimage文件和磁盘edits文件会进行合并
这个合并工作就是SecondaryNameNode执行的
元数据合并过程:
1)合并触发的条件(满足任意一条即执行):
a)时间间隔3600 1h
dfs.namenode.checkpoint.period
3600
The number of seconds between two periodic checkpoints.
b)数据的条数 日志条数 1000000
dfs.namenode.checkpoint.txns
1000000
The Secondary NameNode or CheckpointNode will create a checkpoint
of the namespace every 'dfs.namenode.checkpoint.txns' transactions, regardless
of whether 'dfs.namenode.checkpoint.period' has expired.
元数据合并的过程:
元数据文件的编号的事:
edits的编号从1 开始顺序递增的 记录edits文件的顺序
fsimage文件的编号:编号从0开始的
后续的编号根据每次合并的edits文件的最大编号来的
fsimage_0000000000000000257===
fsimage_0000000000000000000 + edits_0000000000000000001 ~ edits_0000000000000000257
fsimage_0000000000000000350===
fsimage_0000000000000000257+
edits_0000000000000000258~ edits_0000000000000000350
注意:每次集群进行关闭的时候内存中的元数据释放了
集群只要关闭 正在编辑的edits文件也会进行回滚
下次启动的时候内存中的元数据重新从磁盘中加载
edits_0000000000000000255-0000000000000000257
edits_0000000000000000258
fsimage_0000000000000000257
加载的元数据是
1)id最大的fsimage文件
2)edits(fsimage id+1~ seen_txid 中记录的id的所有的edits文件)
namenode边加载 边修改 这样才能保证集群启动的时候的内存的元数据最新的
磁盘中完整的元数据:
fsimage_id +
edits_(fsimage_id+1 ~ seen_txid)