HADOOP NAMENODE FORMAT过程分析

2019-03-28 13:23|来源: 网络

namenode format操作是使用Hadoop分布式文件系统前的步骤。如果不执行这个步骤,无法正确启动分布式文件系统。所以个人认为有必要对这个过程进行分析。

(1)启动format

hadoop namenode -format

在之前关于start-dfs.sh的脚本分析过程,已经介绍到hadoop的脚本,namenode对应的执行类是org.apache.hadoop.hdfs.server.namenode.NameNode类,传入的-format参数传入到执行类,作为执行类的参数。

(2)NameNode的入口main函数

try {
      StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);
      NameNode namenode = createNameNode(argv, null);
//通过createNameNode方法创建NameNode对象,并传入参数,这里传入的是-format
      if (namenode != null)
        namenode.join();
    } catch (Throwable e) {
      LOG.error(StringUtils.stringifyException(e));
      System.exit(-1);
    }

(3)NameNode.createNameNode创建NameNode实例

if (conf == null)
      conf = new Configuration();
//创建Configuration实例,获取配置参数。
    StartupOption startOpt = parseArguments(argv); //解析参数
    if (startOpt == null) {
      printUsage();
      return null;
    }
    setStartupOption(conf, startOpt);


    switch (startOpt) {
      case FORMAT:    
 //对应-format参数
        boolean aborted = format(conf, true); //执行format()
        System.exit(aborted ? 1 : 0);              //执行后,直接退出,并不启动namenode服务
      case FINALIZE:
        aborted = finalize(conf, true);
        System.exit(aborted ? 1 : 0);
      default:
    }
    DefaultMetricsSystem.initialize("NameNode");    
//如果不是-format和-finalize参数,则创建NameNode实例,启动namenode服务
    NameNode namenode = new NameNode(conf);
    return namenode;

(3)执行NameNode.format格式化hdfs操作

这个过程是整个format的流程的主要部分,里面设计到FSNamesystem和FSImage两个和hdfs文件系统关系密切的类。在这里并不展开说明,仅对其和format相关的操作进行分析

Collection<File> dirsToFormat = FSNamesystem.getNamespaceDirs(conf); //通过配置文件配置参数获取fsimage文件所存放的目录,本文后面的部分会单独介绍fsimage文件
    Collection<File> editDirsToFormat = 
                 FSNamesystem.getNamespaceEditsDirs(conf);                                
 //通过配置文件配置参数获取edits文件所存放的目录,本文后面的部分会单独介绍edits文件
    //下面的for循环,用于验证fsimage存放的目录,如果已存在,需要用户确认是否要格式化,如果不允许格式化,则退出。

    for(Iterator<File> it = dirsToFormat.iterator(); it.hasNext();) {
      File curDir = it.next();
      if (!curDir.exists())
        continue;
      if (isConfirmationNeeded) {
        System.err.print("Re-format filesystem in " + curDir +" ? (Y or N) ");
        if (!(System.in.read() == 'Y')) {
          System.err.println("Format aborted in "+ curDir);
          return true;
        }
        while(System.in.read() != '\n'); // discard the enter-key
      }
    }


    //这里分两个步骤,一个是new FSImage,一个是new FSNamesystem.

   //new FSImage调用了FSImage的setStorageDirectories方法,将fsimage和edits目录都存放在StorageDirectory列表storageDirs中

   //并且每个StorageDirectory以NameNodeDirType为IMAGE_AND_EDITS、IMAGE、EDITS来区分。

   //new FSNamesystem创建了HDFS文件系统的根目录FSDirectory对象dir和DelegationTokenSecretManager对象dtSecretManager(这个还不明白是做什么用的)。
    FSNamesystem nsys = new FSNamesystem(new FSImage(dirsToFormat,
                                         editDirsToFormat), conf);

    //最后,就是调用FSImage对象来完成format操作了,这也是整个文件系统格式化的核心过程。
    nsys.dir.fsImage.format();

(4)FSImage.format

    //初始化系统的基本信息,包括版本信息,文件系统的编号等

    this.layoutVersion = FSConstants.LAYOUT_VERSION;
    this.namespaceID = newNamespaceID();
    this.cTime = 0L;
    this.checkpointTime = FSNamesystem.now();

    //这个for循环,就是对之前提到的storageDirs列表的遍历,对每个StorageDirectory对象进行format操作
    for (Iterator<StorageDirectory> it = 
                           dirIterator(); it.hasNext();) {
      StorageDirectory sd = it.next();

     //这个功能较简单,主要分两个步骤

     //调用clearDirectory完全删除sd所在的目录,然后再创建空目录
     //调用saveCurrent创建sd目录下的current目录和fsimage目录及相关文件。具体的创建过程就不分析了,下面的部分就对name目录结构进行分析

      format(sd);
    }

(5)saveCurrent(sd)过程分析

File curDir = sd.getCurrentDir(); //获取sd目录下的current目录
    NameNodeDirType dirType = (NameNodeDirType)sd.getStorageDirType(); //读取目录类型,前面说过,有三种
    // save new image or new edits
    if (!curDir.exists() && !curDir.mkdir())
      throw new IOException("Cannot create directory " + curDir);
    if (dirType.isOfType(NameNodeDirType.IMAGE))
//如果是image或imageandedit类型,创建fsimage文件,并写入根目录信息
      saveFSImage(getImageFile(sd, NameNodeFile.IMAGE));
    if (dirType.isOfType(NameNodeDirType.EDITS))
      editLog.createEditLogFile(getImageFile(sd, NameNodeFile.EDITS)); 
//如果是edit或imageandedit类型,创建edits文件,并写入版本信息
    // write version and time files
    sd.write();
//写入支持旧版本的fsimage目录内容、写入版本信息到VERSION文件中、写入当前系统时间到fstime目录中

(6)name目录结构分析

相关问答

更多
  • 很酷,我找到了解决方案。 停止所有运行的服务器 1) stop-all.sh 编辑文件/usr/local/hadoop/conf/hdfs-site.xml并添加下面的配置(如果缺失) dfs.data.dir /app/hadoop/tmp/dfs/name/data true d ...
  • Hadoop namenode -format Hadoop namenode目录包含fsimage和编辑文件,其中包含有关hadoop文件系统的基本信息,例如数据可用位置,用户创建的文件 如果格式化namenode,那么以上信息将从hdfs-site.xml中指定的namenode目录中删除为dfs.namenode.name.dir 但是你仍然拥有hadoop的数据,但不包含namenode元数据 Hadoop namenode -format Hadoop namenode directory con ...
  • 这不是一个错误。 在启动HDFS之前,您需要格式化namenode。 这与运行Linux / Windows之前需要格式化磁盘相似。 This is not an error. Before you can start HDFS, you need to format the namenode. This is similar to before you can run Linux/Windows you need to format the disk.
  • 它没有从导出的变量中获取类名。 您可以尝试从脚本中注释掉这一行并尝试: export HADOOP_OPTS=”-Djava.security.krb5.realm= -Djava.security.krb5.kdc=” Its not getting the class name from the exported variable. You can try commenting out this line from the script and try: export HADOOP_OPTS=”-Dj ...
  • 这很简单 - 格式化你的名字节点 mcbatyuk:hadoop bam$ bin/hadoop namenode -format Warning: $HADOOP_HOME is deprecated. 12/04/11 21:04:55 INFO namenode.NameNode: STARTUP_MSG: /************************************************************ STARTUP_MSG: Starting NameNode STA ...
  • 你必须将hadoop-hdfs-2.7.0.jar添加到你的hadoop类路径中。 只需在$ HADOOP_HOME / etc / hadoop / hadoop-env.sh中添加以下行: export HADOOP_HOME=/path/to/hadoop export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HADOOP_HOME/share/hadoop/hdfs/hadoop-hdfs-2.7.0.jar 现在,停止所有hadoop进程。 尝试现在格式化name ...
  • 最重要的是名称节点中的META数据。 数据节点可能具有副本形式的数据副本。 但是如果删除或更改了namenode .META,那么数据应该丢失,因为它是格式化命令。 The most important thing is the META data in your name node. Data nodes might have a copy of the data in the form of replicas. But If the namenode .META is deleted or altere ...
  • 这取决于您所讨论的Hadoop版本。 在Hadoop 2之前, Namenode是一个单点故障,所以如果它失败意味着你的集群变得无法使用。 在这种情况下,即使SecondaryNameNode也没有帮助,因为它仅用于检查点,而不是用作NameNode的备份。 当NameNode失败时,像管理员这样的人必须手动重启NameNode 。 但是从Hadoop 2开始,你有更好的方法来处理NameNode失败。 您可以并排运行2个冗余NameNodes ,这样,如果其中一个Namenodes失败,群集将快速故障转移 ...
  • 您在hadoop-env.sh中错误地设置了JAVA_HOME。 给出java_home的绝对路径。你可以使用下面的命令找出java当前的java路径: alternatives --config java 它将提供您已安装的所有Java版本并选择正确的版本并将此java路径设置为hadoop-env.sh,如下所示: export JAVA_HOME=/usr/java/jdk1.*/bin 另一种方法是将$ JAVA_HOME设置为用户的.bashrc。 所以不需要设置为hadoop-env.sh ...
  • 谢谢你的建议。 事实证明它是一个blooper,我只放了两个/而不是文件中给出的三个URI。 它现在有效! thanks for the suggestions. It turned out to be a blooper, I have put only two /'s instead of three as given in the document for the URI. It works now !