一、NameNode和Secondary NameNode工作机制
左侧为NameNode 右侧为Secondary NameNode
1.第一阶段:namenode启动
-
第一次启动namenode格式化后,创建fsimage和edits文件,如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
-
客户端对元数据镜像增删改的请求
-
namenode记录操作日志,更新滚动日志
-
namenode在内存中对数据镜像增删改查
2.第二阶段:Secondary NameNode工作
-
Secondary NameNode询问namenode是否需要checkpoint。直接带回namenode是否检查结果
-
Secondary NameNode请求执行checkpoint
-
namenode滚动正在写的edits日志
-
将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode
-
Secondary NameNode加载编辑日志和镜像文件到内存,开始合并。
-
生成新的镜像文件fsimage.chkpoint
-
拷贝fsimage.chkpoint到namenode
-
nodenode将fsimage.chkpoint重新命名成fsimage
二、镜像文件和编辑日志
namenode被格式化之后,将在日志存放的地方生成四个文件(默认在/tmp/hadopp-用户名/dfs/home/current目录中)
-
Fsimage文件:HDFS文件系统元数据的一个永久性检查点,其中包含HDFS文件系统的所有目录和文件idnode的序列化信息
-
Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到edits文件中。
-
seen_txid文件保存的是一个数字,就是最后一个edits_的数字
-
VERSION文件:namenode版本号
-
每次Namenode启动的时候都会将fsimage文件读入内存,并从00001开始到seen_txid中记录的数字依次执行每个edits里面的更新操作,保证内存的元数据信息是最新的、同步的,可以看成Namenode启动的时候就将fsimage和edits文件进行了合并。
三、查看fsimage文件和edits文件
1.使用oiv命令查看fsimage文件
hdfs oiv -p 转换成的文件类型 -i fsimage文件路径 -o 转换后文件输出的路径
-
一般转换为xml类型
2.使用oev命令查看edits文件
hdfs oev -p 转换成的文件类型 -i fsimage文件路径 -o 转换后文件输出的路径
3.使用dfsadmin命令滚动编辑日志
hdfs dfsadmin -rolledits
-
一般在测试的时候使用
-
会将之前的日志文件打包成旧版本,生成新的增量日志
四、查看VERSION文件
-
namespaceID在HDFS上,会有多个namenode,所以不同namenode的namespaceID是不同的,分别管理一组blockpoolID
-
clusterID集群id,全局唯一
-
cTime属性标记了namenode存储系统的创建时间,对于刚刚格式化的文件系统,这个属性为0;但是在文件系统升级之后,该值会更新到新的时间戳
-
storageType属性说明该存储目录包含的是namenode的数据结构
-
blockpoolID:一个block pool id标识一个block pool,并且是跨集群的全局唯一,当一个新的Namespace被创建的时候(format过程的一部分)会创建并持久化一个唯一ID。在创建工程构建全局唯一的BlockPoolID比人为的配置更可靠一些。NN将BlockPoolID持久化到磁盘中,在后续的启动过程中,会再次load并使用。
-
layoutVersion是一个负整数,通常只有HDFS增加新特性时才会更新这个版本号。
五、修改SecondaryNameNode检查点时间
hdfs-default.xml
1.通常情况下,SecondaryNameNode每个一小时执行一次
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
</property>
2.一分钟检查一次操作次数,当操作次数达到1百万次,SecondaryNameNode也将执行一次
<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
</property>
#六十秒检测一次操作次数
<property>
<name>dfs.namenode.checkpoint.check.period</name>
<value>60</value>
</property>
六、NameNode故障处理
NameNode故障后,可以采用以下两种方法恢复数据。
-
将SecondaryNameNode中数据拷贝到namenode存储数据的目录中
-
使用-importCheckpoint选项启动namenode守护进程,从而将SecondaryNameNode中数据拷贝到namenode目录中
1.手动拷贝SecondaryNameNode数据
-
模拟NameNode故障,手动杀死namenode进程kill -9 namenode进程
-
删除namenode存储的数据(默认在/tmp/hadoop-用户名/dfs/name)rm -rf /tmp/hadoop-用户名/dfs/name/*
-
拷贝SecondaryNameNode中数据拷贝到原namenode存储数据目录中(SecondaryNameNode数据默认在/tmp/hadoop-用户名/dfs/namesecondary)
-
重启namenode hadoop-daemon.sh start namenode
2.通过-importCheckpoint修复数据
修改hdfs-site.xml
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>120</value>
</property>
<property
<name>dfs.namenode.name.dir</name>
<value>{namenode数据文件所在的路径}</value>
</property>
-
模拟NameNode故障,手动杀死namenode进程kill -9 namenode进程
-
删除namenode存储的数据(默认在/tmp/hadoop-用户名/dfs/name)rm -rf /tmp/hadoop-用户名/dfs/name/*
-
如果SecondaryNameNode不和Namenode在一个主机节点上,需要将SecondaryNameNode存储数据的目录拷贝到Namenode存储数据的平级目录,并删除掉in_use.lock文件
-
执行hdfs namenode -importCheckpoint
-
重启namenode hadoop-daemon.sh start namenode
七、集群安全模式操作
NameNode启动时,首先将映像文件(fsimage)载入内存,并执行编辑日志(edits)中的各项操作,一旦在内存中成功建立文件系统元数据的映像,则创建一个新的fsimage文件和一个空的编辑日志。此时namenode开始监听datanode请求。但是此刻,namenode运行在安全模式,即namenode的文件系统对于客户端来说是只读的
系统中的数据块的位置并不是由namenode维护的,而是以块列表的形式储存在datanode中。在系统的正常操作期间,namenode会在内存中保留所有块位置的映射信息。在安全模式下,各个datanode会向namenode发送最新的快列表信息,namenode了解到最够多的块位置信息之后,即可高效运行文件系统。
如果满足“最小副本条件”,namenode会在30秒钟之后就退出安全模式。所谓的最小副本条件指的是在整个文件系统中99%的块满足最小副本级别(默认值:dfs.replication.min=1)。在启动一个刚刚格式化的HDFS集群时,应为系统中还没有任何块,所以namenode不会进入安全模式
1.基本语法
集群处于安全模式,不能执行重要操作(写操作)。集群启动完成后,自动退出安全模式。
-
查看安全模式状态:hdfs dfsadmin -safenode get
-
进入安全模式状态:hdfs dfsadmin -safenode enter
-
退出安全模式状态:hdfs dfsadmin -safenode leave
-
等待安全模式状态:hdfs dfsadmin -safenode wait
2.使用等待安全模式
-
先进入安全模式
-
编写一个脚本,执行脚本
#!/bin/bash
hdfs dfsadmin -safenode wait
#当退出安全模式之后脚本将继续向下执行
hdfs dfs -put ~/hello.txt /root/hello.txt
八、namenode多目录配置
namenode的本地目录可以配置成多个,且每个目录存放内容相同,增加了可靠性。
-
停止集群,并删除data和logs中所有数据
-
配置hdfs-site.xml文件,重新格式化hdfs并启动
<property>
<name>dfs.namenode.name.dir</name>
<value>file://{文件放的路径}/dfs/name1,file://{文件放的路径}/dfs/name2</value>
</property>