namenode元数据管理要点
什么是元数据?
hdfs的目录结构及每一个文件的块信息(块的id,块的副本数量,块的存放位置<datanode>)
元数据由谁负责管理?
namenode
namenode把元数据记录在哪里?
1. namenode的实时的完整的元数据存储在内存中; 2. namenode还会在磁盘中(dfs.namenode.name.dir)存储内存元数据在某个时间点上的镜像文件; 3. namenode会把引起元数据变化的客户端操作记录在edits日志文件中;
Namenode主要维护两个文件,一个是fsimage,一个是editlog。
- fsimage保存了最新的元数据检查点,包含了整个HDFS文件系统的所有目录和文件的信息。对于文件来说包括了数据块描述信息、修改时间、访问时间等;对于目录来说包括修改时间、访问权限控制信息(目录所属用户,所在组)等。
- editlog主要是在NameNode已经启动情况下对HDFS进行的各种更新操作进行记录,HDFS客户端执行所有的写操作都会被记录到editlog中。
- 简单来说,NameNode维护了文件与数据块的映射表-以及数据块与数据节点的映射表,什么意思呢?就是一个文件,它切分成了几个数据块,以及这些数据块分别存储在哪些datanode上,namenode一清二楚。
- Fsimage就是在某一时刻,整个hdfs 的快照,就是这个时刻hdfs上所有的文件块和目录,分别的状态,位于哪些个datanode,各自的权限,各自的副本个数。
- 然后客户端对hdfs所有的更新操作,比如说移动数据,或者删除数据,都会记录在editlog中。
- 为了避免editlog不断增大,secondary namenode会周期性合并fsimage和edits成新的fsimage,新的操作记录会写入新的editlog中,这个周期可以自己设置(editlog到达一定大小或者定时)。
secondarynamenode
- secondarynamenode会定期从namenode上下载fsimage镜像和新生成的edits日志,然后加载fsimage镜像到内存中,然后顺序解析edits文件,对内存中的元数据对象进行修改整合完成后,将内存元数据序列化成一个新的fsimage,并将这个fsimage镜像文件上传给namenode
上述过程叫做:checkpoint操作
提示:secondary namenode每次做checkpoint操作时,都需要从namenode上下载上次的fsimage镜像文件吗?
- 第一次checkpoint需要下载,以后就不用下载了,因为自己的机器上就已经有了。
可以很清晰看出
第一步:将hdfs更新记录写入一个新的文件——edits.new。
第二步:将fsimage和editlog通过http协议发送至secondary namenode。
第三步:将fsimage与editlog合并,生成一个新的文件——fsimage.ckpt。这步之所以要在secondary namenode中进行,是因为比较耗时,如果在namenode中进行,或导致整个系统卡顿。
第四步:将生成的fsimage.ckpt通过http协议发送至namenode。
第五步:重命名fsimage.ckpt为fsimage,edits.new为edits。
- 这样的话,fsimage与editlog合并的过程就完成了。所以如果namenode宕机,其实secondary namenode还保存这一份不久前的fsimage,还能挽回一些损失吧。
- 另外,一旦有datanode挂掉了(宕机或者是网络阻塞),namenode能很快感知到,并且将宕机的节点上的数据块转移至其余空闲节点。这点是因为hdfs中心跳机制(heartbeat)。
- 心跳机制默认3s中一次,datanode会向namenode发送一次一跳,告知namenode当前节点上存放的数据文件是什么。如果namenode中记录的是该datanode存放了文件A的两个数据块和文件B的一个数据块,但是心跳中只有文件A的一个数据块信息,namenode就会知道该datanode数据块损坏了,会把损坏的数据块在别的datanode上补充。
补充:secondary namenode启动位置的配置
<property> <name>dfs.namenode.secondary.http-address</name> <value>0.0.0.0:50090</value> </property>
- 把默认值改成你想要的机器主机名即可
secondarynamenode保存元数据文件的目录配置:
<property> <name>dfs.namenode.checkpoint.dir</name> <value>file://${hadoop.tmp.dir}/dfs/namesecondary</value> </property>
- 改成自己想要的路径即可:/root/dfs/namesecondary