一、思考: NameNode中的元数据是存储在哪里?
不废话直接上答案(简明扼要的思考步骤)。
-
存入磁盘?错
原因:经常进行随机访问、还要响应客户请求。通过存放磁盘效率太低。
-
存入内存?错
原因:一旦断电,元数据丢失,整个集群就无法工作。
注意:因此产生在磁盘中备份元数据的FsImage。
-
产生了新问题:
1、当内存中的元数据更新时,如果同时更新FsImage,就会导致效率过低。
2、不更新时,就会产生一致性问题,一旦NameNode节点断电,内存中的元数据就会丢失。
-
解决办法:
引入Edits文件(只进行追加操作,效率很高)。
原因:每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中(追加的是操作而不是操作结果)。这样,一旦NameNode节点断电,可以通过FsImage和Edits的合并,合成元数据。
-
又产生了新问题:
1、长时间添加数据到Edits中,会导致该文件数据过大,效率降低。
2、一旦断电,恢复元数据(FsImage和Edits的合并)需要的时间过长。
-
解决办法:
1、定期进行FsImage和Edits的合并。
2、引入新的节点(Secondary NameNode),专门用于FsImage和Edits的合并。缓解NameNode的压力,提升效率。
二、NameNode和Secondary NameNode工作机制
第一阶段:NameNode启动
- 第一次启动NameNode格式化后,创建FsImage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存中。
- 客户端对元数据进行增删改的请求。
- NameNode记录操作日志,更新滚动日志。
- NameNode在内存中对元数据进行增删改。
第二阶段:Secondary NameNode工作
- Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。
- Secondary NameNode请求执行CheckPoint。
- NameNode滚动正在写的Edits日志。
- 将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。
- Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
- 生成新的镜像文件fsimage.chkpoint。
- 拷贝fsimage.chkpoint到NameNode。
- NameNode将fsimage.chkpoint重新命名成fsimage。
三、Fsimage和Edits概念
NameNode被格式化后,会产生以下文件:
-
fsimage_0000000000000000000
-
fsimage_0000000000000000000.md5
-
seen_txid
-
VERSION
-
Fsimage文件(HDFS文件系统镜像):HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所以目录和文件inode的序列化信息。每个inode表征一个文件或目录的元数据信息以及文件的副本数、修改和访问时间等信息。
-
Edits文件(编辑日志):存放HDFS文件系统的所以更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到Edits文件中。
-
seen_txid文件:里面保存的是一个数字N,format(格式化)之后是0,代表的是edits_*文件中的尾数。NameNode重启时会按照seen_txid里的数字,循序从头跑edits_0000001~edits_000000N。
注意:当HDFS异常重启时,一定要检查seen_txid内的数字和edits_*文件的尾数是否匹配,否则会发生建置NameNode时metaData的资料有缺少,导致误删DataNode上多余的Block的资讯。
-
VERSION文件:Java属性文件,保存了HDFS的版本号。
-
每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并。