Hadoop3.2.1 【 HDFS 】源码分析 : NameNode -format 解析

一.前言

众所周知, 在安装hadoop的时候, 必须对hdfs的Namenode进行格式化操作. 本文主要介绍格式化操作.

 

格式化命令如下.

         bin/hdfs namenode -format

 

二.代码入口

Namenode的格式化操作是 : org.apache.hadoop.hdfs.server.namenode.NameNode

/**
   */
  public static void main(String argv[]) throws Exception {
    //参数校验
    if (DFSUtil.parseHelpArgument(argv, NameNode.USAGE, System.out, true)) {
      System.exit(0);
    }

    try {
      StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);

      //调用createNameNode()方法创建NameNode对象
      NameNode namenode = createNameNode(argv, null);

      if (namenode != null) {
        //等待Namenode RPC服务结束
        namenode.join();
      }
    } catch (Throwable e) {
      LOG.error("Failed to start namenode.", e);
      //出现异常则直接退出执行
      terminate(1, e);
    }
  }

 

通过main入口的方法,我们可以知道接下来是调用createNameNode方法. 然后根据传入的参数不同执行不同的代码片段.

我们主要是看格式化操作, 我们关注一下 FORMAT 这个代码片段就可以了.

public static NameNode createNameNode(String argv[], Configuration conf)
      throws IOException {
    LOG.info("createNameNode " + Arrays.asList(argv));

    //构建配置文件
    if (conf == null)
      conf = new HdfsConfiguration();

    // Parse out some generic args into Configuration.
    GenericOptionsParser hParser = new GenericOptionsParser(conf, argv);
    argv = hParser.getRemainingArgs();

    // Parse the rest, NN specific args.
    //解析命令行的参数
    StartupOption startOpt = parseArguments(argv);
    if (startOpt == null) {
      printUsage(System.err);
      return null;
    }
    setStartupOption(conf, startOpt);

    boolean aborted = false;

    //根据启动选项调用对应的方法执行操作
    switch (startOpt) {

    //格式化当前Namenode, 调用format()方法执行格式化操作
    case FORMAT:
      aborted = format(conf, startOpt.getForceFormat(),
          startOpt.getInteractiveFormat());
      terminate(aborted ? 1 : 0);
      return null; // avoid javac warning
    case GENCLUSTERID:
      // 代码略...

    //回滚上一次升级, 调用doRollback()方法执行回滚操作。
    case ROLLBACK:
      // 代码略...

    // 拷贝Active Namenode的最新命名空间数据到StandbyNamenode,
    // 调用BootstrapStandby.run()方法执行操作
    case BOOTSTRAPSTANDBY:
     // 代码略...

    //初始化editlog的共享存储空间, 并从Active
    //Namenode中拷贝足够的editlog数据, 使得Standby节点能够顺利启动。 这里调用
    //了静态方法initializeSharedEdits()执行操作
    case INITIALIZESHAREDEDITS:
      // 代码略...
    case BACKUP:


    //启动checkpoint节点, 也是直接构造BackupNode对象并返回。
    case CHECKPOINT:
      // 代码略...

    //恢复损坏的元数据以及文件系统, 这里调用了doRecovery()方法执行操作
    case RECOVER:
      // 代码略...

    //确认配置文件夹存在, 并且打印fsimage文件和文件系统的元数据版本
    case METADATAVERSION:
      // 代码略...

    //升级Namenode, 升级完成后关闭Namenode。
    case UPGRADEONLY:
      // 代码略...


    //在默认情况下直接构造NameNode对象并返回
    default:
      // 初始化 度量服务
      DefaultMetricsSystem.initialize("NameNode");
      //  构建NameNode
      return new NameNode(conf);
    }
  }

 

所以我们主要关注format方法即可.

 

三.格式化操作 format

这里我就不细说了,后面在说FSNamesystem的时候,会做详细讲解. 这里大概就是 生成一个集群id

[clusterId : 规则 CID-UUID 如: CID-d5e21420-46b8-41fb-acc7-8562be611472]

然后构建一个FSImage

// 构建 FSImage
FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat);

然后根据FSImage构建和配置文件构建 FSNamesystem, 最后再调用:

fsImage.format(fsn, clusterId, force);

这个进行初始化操作. 生成文件.

/**
   * Verify that configured directories exist, then
   * Interactively confirm that formatting is desired 
   * for each existing directory and format them.
   * 
   * @param conf configuration to use
   * @param force if true, format regardless of whether dirs exist
   * @return true if formatting was aborted, false otherwise
   * @throws IOException
   */
  private static boolean format(Configuration conf, boolean force,  boolean isInteractive) throws IOException {
    // nsId =  null
    String nsId = DFSUtil.getNamenodeNameServiceId(conf);
    // namenodeId =  null
    String namenodeId = HAUtil.getNameNodeId(conf, nsId);

    initializeGenericKeys(conf, nsId, namenodeId);
    //读取配置dfs.namenode.support.allow.format  namenode是否可以格式化: 默认true
    checkAllowFormat(conf);

    if (UserGroupInformation.isSecurityEnabled()) {
      InetSocketAddress socAddr = DFSUtilClient.getNNAddress(conf);
      SecurityUtil.login(conf, DFS_NAMENODE_KEYTAB_FILE_KEY,
          DFS_NAMENODE_KERBEROS_PRINCIPAL_KEY, socAddr.getHostName());
    }
    
    Collection<URI> nameDirsToFormat = FSNamesystem.getNamespaceDirs(conf);

    // list<URI> 0 : file:/tools/hadoop-3.2.1/data/namenode
    List<URI> sharedDirs = FSNamesystem.getSharedEditsDirs(conf);


    List<URI> dirsToPrompt = new ArrayList<URI>();


    dirsToPrompt.addAll(nameDirsToFormat);
    dirsToPrompt.addAll(sharedDirs);

    // list<URI> 0 : file:/tools/hadoop-3.2.1/data/namenode
    List<URI> editDirsToFormat =  FSNamesystem.getNamespaceEditsDirs(conf);

    // if clusterID is not provided - see if you can find the current one
    String clusterId = StartupOption.FORMAT.getClusterId();
    if(clusterId == null || clusterId.equals("")) {
      //Generate a new cluster id   生成新的id  举例: CID-UUID  ==>  CID-d5e21420-46b8-41fb-acc7-8562be611472
      clusterId = NNStorage.newClusterID();
    }
    System.out.println("Formatting using clusterid: " + clusterId);
    // 构建 FSImage
    FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat);

    //构建 FSNamesystem
    try {
      FSNamesystem fsn = new FSNamesystem(conf, fsImage);
      fsImage.getEditLog().initJournalsForWrite();

      // Abort NameNode format if reformat is disabled and if
      // meta-dir already exists
      if (conf.getBoolean(DFSConfigKeys.DFS_REFORMAT_DISABLED,
          DFSConfigKeys.DFS_REFORMAT_DISABLED_DEFAULT)) {
        force = false;
        isInteractive = false;
        for (StorageDirectory sd : fsImage.storage.dirIterable(null)) {
          if (sd.hasSomeData()) {
            throw new NameNodeFormatException(
                "NameNode format aborted as reformat is disabled for "
                    + "this cluster.");
          }
        }
      }

      if (!fsImage.confirmFormat(force, isInteractive)) {
        return true; // aborted
      }

      //
      fsImage.format(fsn, clusterId, force);


    } catch (IOException ioe) {
      LOG.warn("Encountered exception during format: ", ioe);
      fsImage.close();
      throw ioe;
    }
    return false;
  }

 

四. 格式化后生成的文件&内容

格式化之后,会在配置namenode的目录生成一个current文件夹,里面会有四个文件.

VERSION    记录版本信息
fsimage_0000000000000000000.md5   记录fsimage_0000000000000000000对应的md5
fsimage_0000000000000000000 namenode对应的fsimage文件
seen_txid 事务标识

 

-rw-r--r--@ 1 sysadmin  staff  218  9  6 22:11 VERSION
-rw-r--r--@ 1 sysadmin  staff  401  9  6 22:13 fsimage_0000000000000000000
-rw-r--r--  1 sysadmin  staff   62  9  6 22:13 fsimage_0000000000000000000.md5
-rw-r--r--@ 1 sysadmin  staff    2  9  6 22:11 seen_txid

1.VERSION 文件:


#Sun Sep 06 22:11:02 CST 2020
namespaceID=1147175932
clusterID=CID-d5e21420-46b8-41fb-acc7-8562be611472
cTime=1599401184918
storageType=NAME_NODE
blockpoolID=BP-1598486647-192.168.8.156-1599401184918
layoutVersion=-65

 

2.seen_txid :  只是存储了一个数字 0

 

3.fsimage_0000000000000000000.md5  记录fsimage_0000000000000000000 对应的md5 值

48dd36a9bd6e7ad0ca017afbef91c7cb *fsimage_0000000000000000000

4.fsimage_0000000000000000000

 这里面的内容比较繁琐主要包含以下信息:
 

保存命名空间信息
保存 ErasureCoding 信息
保存命名空间中的inode信息
保存快照信息
保存安全信息
保存缓存信息
保存StringTable

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个问题是指 Hadoop 的 NameNode 未被格式化。要解决这个问题,需要执行以下步骤: 1. 关闭 Hadoop 集群中所有节点的服务。 2. 在 NameNode 所在节点上运行以下命令来格式化 NameNodehadoop namenode -format 3. 启动 Hadoop 集群中的所有服务。 执行完这些步骤后,您应该能够成功启动 Hadoop 集群。 ### 回答2: 当我们启动Hadoop的时候,如果出现"namenode is not formatted"的错误信息,意味着NameNode的元数据目录没有被正确格式化。 要解决这个问题,可以按照下面的步骤进行操作: 1. 停止所有的Hadoop服务,包括NameNode、DataNode和ResourceManager等。 2. 在主节点的Hadoop文件系统中找到NameNode的元数据目录,通常是在core-site.xml文件中配置的"dfs.namenode.name.dir"属性的指定路径下。可以使用命令`grep "dfs.namenode.name.dir" core-site.xml`来查找该路径。 3. 进入NameNode元数据目录,并删除其中的所有文件和子目录。可以使用命令`rm -Rf <metadata_dir>/*`来删除所有文件和子目录。 4. 重新格式化NameNode元数据目录。可以使用命令`hdfs namenode -format`来重新格式化。 5. 启动Hadoop服务。可以使用命令`start-all.sh`来启动所有的Hadoop服务。 在完成以上步骤后,再次启动Hadoop,"namenode is not formatted"的错误信息应该不再出现。同时,注意确保配置文件的正确性和一致性,以及确保所有的Hadoop服务正常运行。 ### 回答3: "namenode is not formatted"表示NameNode未进行格式化。在Hadoop中,NameNode负责存储并管理整个文件系统的元数据信息。当遇到“namenode is not formatted”错误时,可以通过以下步骤解决: 1. 停止Hadoop集群:停止所有节点上的Hadoop服务(包括NameNode和DataNode)。 2. 删除Hadoop文件系统元数据:在NameNode节点上找到Hadoop文件系统的数据存储位置(可在hdfs-site.xml文件中找到),通常是hadoop.tmp.dir指定的目录。删除此目录下的所有数据,包括所有子目录和文件。 3. 格式化NameNode:在NameNode节点上运行以下命令进行格式化: ```shell hdfs namenode -format ``` 4. 启动Hadoop集群:启动所有节点上的Hadoop服务。在NameNode节点上执行以下命令: ```shell start-dfs.sh ``` 确保NameNode和DataNode都已成功启动。 5. 验证解决方案:使用以下命令检查Hadoop集群状态: ```shell hdfs dfsadmin -report ``` 如果状态报告正常显示,即表示问题已解决。 需要注意的是,执行这些步骤将删除Hadoop集群中存储的所有数据,包括HDFS中的文件。因此,在执行此操作之前,请确保备份了重要的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值