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)创建元数据文件在内存中的镜像:

内存镜像包括:

  1. 类FSNamesystem对象
  2. 类FSDirectory对象
  3. 类FSImage对象
  4. 类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