Hadoop--HDFS之NameNode
之前就打算写一下Hadoop系列博客的,由于写别的东西去了,一直也没抽空出来,上篇Hadoop–HDFS架构和Shell对HDFS的一个简单概述,还是两三个月前的事情了。做了这么久的Hadoop了,在这里算是自我总结一下吧,本篇博客主要讲解一下Hadoop HDFS的NameNode。
- 重点掌握:
NameNode
的作用;NameNode
元数据的底层结构;SecondaryNameNode
的作用以及工作流程,以及为什么需要SecondaryNameNode。
NameNode简介
- 管理节点
- 核心元数据,包括文件(夹)的目录结构和属性信息,还有文件与其所在位置的映射信息。
- 一切读写的操作必须经过NameNode,但是传输数据本身不经过NameNode(好好理解这句话)。
NameNode
NameNode 包括以下文件:(保存在linux的文件系统中)
fsimage
:元数据镜像文件,存储某一时段NameNode内存元数据信息即保存了最新的元数据checkpoint。edits
:操作日志文件。fstime
:保存最近一次checkpoint的时间
NameNode 元数据
- NameNode 为了保证交互速度,会在内存中保存这些元数据信息,但同时也会将这些信息保存到硬盘上进行持久化存储;
- fsimage文件是内存中的元数据在硬盘上的checkpoint,它是一种序列化的格式,不能直接修改。
- Hadoop在重启时就是通过
fsimage+edits
来状态恢复,fsimage相当于一个checkpoint,首先将最新的checkpoint的元数据信息从fsimage中加载到内存,然后逐一执行edits修改日志文件中的操作以恢复到重启之前的最终状态。 - Hadoop的持久化过程是将上一次checkpoint以后最近一段时间的操作保存到修改日志文件edits中。
SecondaryNameNode
上面出现的一个问题是:edits会随着时间增加而越来越大,导致以后重启时需要花费很长的时间来按照edits中记录的操作进行恢复,于是Hadoop就专门弄了一个进程SecondaryNameNode。
- SecondaryNameNode节点 的主要功能是周期性将元数据节点的命名空间镜像文件(fsimage)和修改日志(edits)进行合并,以防edits日志文件过大。下面来看一看合并的流程:
- SecondaryNameNode节点 需要合并时,首先通知
NameNode节点
生成新的日志文件,以后的日志都写到新的日志文件中。 - SecondaryNameNode节点 用
http get
从NameNode节点
获得fsimage文件
及旧的edits日志文件
。 - SecondaryNameNode节点 将 fsimage 文件加载到内存中,并执行日志文件中的操作,然后生成新的fsimage文件。
- SecondaryNameNode 节点将新的fsimage文件用http post传回NameNode节点上。
- NameNode 节点可以将旧的fsimage文件及旧的日志文件,换为新的fsimage文件和新的日志文件(第一步生成的),然后更新fstime文件,写入此次checkpoint的时间。
- 这样NameNode 节点中的fsimage文件保存了最新的checkpoint的元数据信息,日志文件也重新开始,不会变的很大了
注意
:
- 这种机制有个问题:因edits存放在NameNode中,当NameNode挂掉,edits也会丢失,导致利用Secondary NameNode恢复Namenode时,会有部分数据丢失。
- HDFS设置了两种机制进行条件合并(hdfs-site.xml):
第一种:当时间间隔大于或者等于dfs.namenode.checkpoint.period配置的时间是做合并(默认一小时)
第二种:当最后一次往journalNode写入的TxId(这个可以在namenode日志或者50070界面可以看到)和最近一次做Checkpoint的TxId的差值大于或者等于dfs.namenode.checkpoint.txns配置的数量(默认1000000)时做一次合并
底层文件查看
保存的
NameNode元数据
信息,在HADOOP_HOME/etc/hadoop/hdfs-site.xml 的 dfs.namenode.name.dir
配置,如下图:1
2
3
4
5
6<property>
<name>dfs.namenode.name.dir</name>
<value>file:///usr/local/hadoop_repo/name</value>
</property>
<!-- 我切换到/usr/local/hadoop_repo/name/current就能查看元数据信息了 -->
<!-- value可以配置多个,用逗号隔开,这样也算是一种备份方式吧-->第一步:开启服务,查看某个fsimage文件,开启服务命令:
bin/hdfs oiv -i fsimage文件
,不然提示:ls: Connection refused第二步:查看内容,命令:
bin/hdfs dfs -ls -R webhdfs://127.0.0.1:5978/
。我的hdfs里面有hbase和hive的数据,所以元数据也比较多,这里来个部分截图(这个看上去就和web
以及hdfs dfs -ls
查看的结果差不多):第三步:导出结果,这是导出fsimage文件内容,命令:
hdfs oiv -p XML -i /usr/local/hadoop_repo/name/current/fsimage_0000000000000003292 -o fsimage.xml
- xml节点在上面大家也能看见,主要看inode节点,下面就是文件以及文件夹的基本信息;
id
、name
、type
、mtime
、permission
、nsquota
、dsquota
;- 如果是文件还有更多属性,比如
atime
、perferredBlockSize
、blocks
等 - fsimage 保存有如下信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21一、加载Img头信息,如下:
1、imgVersion(int):当前image的版本信息
2、namespaceID(int):用来确保别的HDFS instance中的datanode不会误连上当前NN。
3、numFiles(long):整个文件系统中包含有多少文件和目录
4、genStamp(long):生成该image时的时间戳信息。
二 、如果加载目录,包含以下信息:
1、path(String):该目录的路径,如”/user/build/build-index”
2、replications(short):副本数(目录虽然没有副本,但这里记录的目录副本数也为3)
3、mtime(long):该目录的修改时间的时间戳信息
4、atime(long):该目录的访问时间的时间戳信息
5、blocksize(long):目录的blocksize都为0
6、numBlocks(int):文件块数,-1表示目录,大于1时,表示该文件对应有多个block信息
7、nsQuota(long):namespace Quota值,若没加Quota限制则为-1
8、dsQuota(long):disk Quota值,若没加限制则也为-1
9、username(String):该目录的所属用户名
10、group(String):该目录的所属组
11、permission(short):该目录的permission信息,如644等,有一个short来记录。
三、如果加载文件,则还会额外包含如下信息:
1、blockid(long):属于该文件的block的blockid,
2、numBytes(long):该block的大小
3、genStamp(long):该block的时间戳
在namenode启动时,就需要对fsimage按照如下格式进行顺序的加载,以将fsimage中记录的HDFS元数据信息加载到内存中。
- 第三步:继续导出,这是导出edits文件内容,命令:
bin/hdfs oev -i /usr/local/hadoop_repo/name/current/edits_0000000000000003295-0000000000000003296 -o edits.xml
- 最大的节点是
EDITS
,下面就是版本信息EDITS_VERSION
和很多的RECORD
节点; - 每个edits文件第一个
RECORD
的RECORD
都是以OP_START_LOG_SEGMENT
开头; RECORD
类型有很多,比如 OP_ADD、OP_TIMES、OP_DELETE、OP_ALLOCATE_BLOCK_ID、OP_ADD_BLOCK、OP_RENAME_OLD、OP_CLOSE等
- 总结:
- 从上面我们就可以看出,edits文件的信息特别详细,记录了每一步操作,所以文件大小增长也特别的快;
- fsimage文件内容就是edits文件详细步骤的浓缩。