1. 元数据应用的场景:
(1)HDFS初次使用前,要进行格式化,格式化的结果是:
在元数据镜像文件的备份路径current目录下产生元数据文件:fsimage、fstime、VERSION
在日志文件备份路径的current目录下,产生日志文件:edits、fstime、VERSION
(2)启动HDFS时,将fsimage和edits文件读入内存,进行合并。并将新的元数据内存镜像导出,形成新的fsimage和edits
(3)HDFS正常运行,把元数据更新操作作为日志记录写入磁盘文件edits
(4)进行checkpoint的时候,形成当前某一个时刻的fsimage,替代Namenode原有的fsimage,并以新fsimage之后的edits替换原有的edits
2. HDFS的磁盘数据文件:
包括四个:
fsimage ---存储某一时刻NameNode内存元数据信息
eidts ---存储该时刻后元数据的操作记录
fstime ---存储最近一次checkpoint的时间
VERSION ---标志性文件,标示前三个文件创建成功
元数据备份路径的设置:
cp hdfs/src/java/hdfs-default.xml conf/hdfs-site.xml
vi conf/hdfs-site.xml
在其中配置dfs.namenode.name.dir的value,作为fsimage的保存路径,可以配置多个
在其中配置dfs.namenode.edits.dir的value,作为edits的保存路径,可以配置多个
格式化命令:
bin/hdfs namenode format
格式化结果:
应该是在对应目录下产生对应的fsimage,edits和fstime文件,并且导入到内存中
3. Format具体分析:
format的实现步骤——
(1)确定能否格式化;
(2)创建元数据文件在内存中的镜像;
(3)对内存景象中的数据结构初始化;
(4)将内存景象写入元数据备份目录
(1)确定能否格式化:
① bin/hdfs namenode format的入口是类Namenode的main函数
② 在该main函数中主要调用的是createNamenode(argv,conf)函数
③ 在createNamenode函数中,解析设置启动参数,根据不同的启动参数采用不同的处理方法
...
case FORMAT:
boolean aborted = format(conf,true);
System.exit(aborted?1:0);
return null;
...
④ 在format函数中,首先调用FSNamesystem中的静态方法解析conf,从中提取出元数据存储目录
private static boolean format (Configuration conf,boolean isConfirmationNeeded) throws IOException {...}
⑤ 然后通过一个用户交互来决定是否格式化这些目录,如果不同意,则中止
⑥ 然后创建FSNamesystem对象
FSNamesystem nsys = new FSNamesystem(new FSImage(dirsToFormat,editDirsToFormat),conf);
⑦ 调用fsImage中的format()函数来进行真正的format
nsys.dir.fsImage.format();
(2)创建元数据文件在内存中的镜像:
内存镜像包括:
- 类FSNamesystem对象
- 类FSDirectory对象
- 类FSImage对象
- 类FSEdit对象
在(1)中的第⑥步,曾经创建了一个FSNamesystem对象,下面简单说明它的构造函数完成的功能:
FSNamesystem(FSImage fsImage,Configuraiton conf) throw IOException {
this.blockManager = new BlockManager(this,conf);
setConfigurationParameters(conf);
FSDirectory(fsImage,this,conf);
}
可以看出,完成了三个功能:
① 创建类BlockManager对象;
② 读取配置文件,对FSNamesystem成员变量初始化;
③ 创建类FSDirectory对象
在FSNamesystem的构造函数中,FSDirectory的构造函数创建了HDFS根目录的INode节点rootDir:
FSDirectory(FSImage fsImage,FSNamesystem ns,Configuration conf) {
....
rootDir = new INodeDirectoryWithQuota(...);
}
在FSNamesystem对象的创建中,直接new了一个FSImage对象作为参数传入其构造函数,在(1)中的⑥处,下面重点说明一下类FSImage的构造函数及其作用:
public class FSImage extends Storage {
...
FSImage() {
tihs((FSNamesystem)null);
}
FSImage(FSNamesystem ns) {
super(NodeType.NAME_NODE);
this.editLog = new FSEditLog(this);
setFSNamesystem(ns);
}
FSImage(Collection<URI> fsDirs,Collection<URI> fsEditsDirs) thorw IOException {
this();
setStorageDirectories(fsDirs,fsEditsDirs);
}
...
}
FSImage的构造函数主要完成3个动作:
① 成员变量的初始化:类FSImage是类Storage的子类,类Storage又是类StorageInfo的子类,在FSImage第二个构造函数中,调用了父类的构造函数,最终在StorageInfo的构造函数中进行一些列成员变量初始化;
② 实例化FSEditLog对戏那个EditLog;
③ 对备份目录进行分类,加入到storageDIrs,对应于第三个构造函数中setStorageDirectories(fsDirs,fsEditsDirs);
在setStorageDirectories(fsDirs,fsEditsDirs)函数中,先判断fsimage和editlog的目录是否重合,如果重合就直接把fsimage目录添加到storageDir,如果不重合就分别把fsimage和editLog目录添加到storageDir