阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Hadoop-2.4.1学习之创建fsimage和edits源码分析

101次阅读
没有评论

共计 10766 个字符,预计需要花费 27 分钟才能阅读完成。

在 Hadoop 中 fsimage 保存最新的检查点信息,edits 保存自最新检查点后的命名空间的变化。在分析 hdfs namenode–format 的源代码时,已经明确了该过程根据配置文件的信息创建 fsimage 和 edits 文件,这篇文章具体分析一下创建 fsimage 和 edits 文件的源代码。在 NameNode 的 format 方法中,有如下的代码:

FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat);
    try {
      FSNamesystem fsn = new FSNamesystem(conf, fsImage);
      fsImage.getEditLog().initJournalsForWrite();

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

      fsImage.format(fsn, clusterId);
    } catch (IOException ioe) {
      LOG.warn(“Encountered exception during format: “, ioe);
      fsImage.close();
      throw ioe;
    }

在这段代码中主要涉及到了三个类,分别为 FSImage、FSNamesystem 和 FSEditLog,其中 FSImage 负责检查点,FSEditLog 维护命名空间变动的日志,FSNamesystem 为 DataNode 执行实际的簿记工作。创建 fsImage 对象的源代码为

/**
  * Construct the FSImage. Set the default checkpoint directories.
  *
  * Setup storage and initialize the edit log.
  *
  * @param conf Configuration
  * @param imageDirs Directories the image can be stored in.
  * @param editsDirs Directories the editlog can be stored in.
  * @throws IOException if directories are invalid.
  */
  protected FSImage(Configuration conf,Collection<URI> imageDirs,
                    List<URI> editsDirs)throws IOException {
this.conf = conf;
/* NNStorage 负责管理 NameNode 使用的 StorageDirectories*/
storage = new NNStorage(conf, imageDirs, editsDirs);
/* 根据 dfs.namenode.name.dir.restore 的值决定是否尝试重新存储失败的存储目录
* 默认值为 false
*/
    if(conf.getBoolean(DFSConfigKeys.DFS_NAMENODE_NAME_DIR_RESTORE_KEY,
                      DFSConfigKeys.DFS_NAMENODE_NAME_DIR_RESTORE_DEFAULT)) {
      storage.setRestoreFailedStorage(true);
    }
this.editLog = new FSEditLog (conf, storage, editsDirs);
/*NNStorageRetentionManager 负责检查 NameNode 的存储目录,
    * 并在 fsimage 和 edits 文件上执行保留策略。
*/
    archivalManager = new NNStorageRetentionManager(conf, storage, editLog);
  }

FSImage 的构造方法中,创建了 NNStorage、FSEditLog 和 NNStorageRetentionManager 对象,NNStorage 的构造方法源代码如下:

public NNStorage(Configuration conf, Collection<URI> imageDirs, Collection<URI> editsDirs) throws IOException {
    super(NodeType.NAME_NODE);
    storageDirs = new CopyOnWriteArrayList<StorageDirectory>();
   
    // this may modify the editsDirs, so copy before passing in
    setStorageDirectories(imageDirs,
                          Lists.newArrayList(editsDirs),
                          FSNamesystem.getSharedEditsDirs(conf));
  }

NNStorage 中的 setStorageDirectories 方法用于初始化存储 fsimage 和 edits 文件的目录。这里不分析该方法的全部源代码,主要分析初始化 fsimage 的部分,如下:

// Add all name dirs with appropriate NameNodeDirType
    for (URI dirName : fsNameDirs) {
      checkSchemeConsistency(dirName);
      boolean isAlsoEdits = false;
      for (URI editsDirName : fsEditsDirs) {
        if (editsDirName.compareTo(dirName) == 0) {
          isAlsoEdits = true;
          fsEditsDirs.remove(editsDirName);
          break;
        }
      }
      NameNodeDirType dirType = (isAlsoEdits) ?
                          NameNodeDirType.IMAGE_AND_EDITS :
                          NameNodeDirType.IMAGE;
      // Add to the list of storage directories, only if the
      // URI is of type file://
      if(dirName.getScheme().compareTo(“file”) == 0) {
        this.addStorageDir(new StorageDirectory(new File(dirName.getPath()),
            dirType,
            sharedEditsDirs.contains(dirName))); // Don’t lock the dir if it’s shared.
      }
    }

Ubuntu 13.04 上搭建 Hadoop 环境 http://www.linuxidc.com/Linux/2013-06/86106.htm

Ubuntu 12.10 +Hadoop 1.2.1 版本集群配置 http://www.linuxidc.com/Linux/2013-09/90600.htm

Ubuntu 上搭建 Hadoop 环境(单机模式 + 伪分布模式)http://www.linuxidc.com/Linux/2013-01/77681.htm

Ubuntu 下 Hadoop 环境的配置 http://www.linuxidc.com/Linux/2012-11/74539.htm

单机版搭建 Hadoop 环境图文教程详解 http://www.linuxidc.com/Linux/2012-02/53927.htm

搭建 Hadoop 环境(在 Winodws 环境下用虚拟机虚拟两个 Ubuntu 系统进行搭建)http://www.linuxidc.com/Linux/2011-12/48894.htm

更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2014-09/107139p2.htm

在该段代码中 fsNameDirs 和 fsEditsDirs 分别为参数 dfs.namenode.name.dir 和 dfs.namenode.edits.dir 设置的目录,默认情况下二者指向相同的目录。如果二者的值相同那么 fsimage 的类型就为 NameNodeDirType.IMAGE_AND_EDITS,否则为 NameNodeDirType.IMAGE。需要注意的是,到目前为止虽然根据配置文件创建了表示相应目录的 File 对象,但还没有在本地文件系统上创建实际的目录。现在回到 FSIamge 的构造方法中,在创建了 NNStorage 对象后,接下来创建 FSEditLog 对象,该类的构造方法为:

/**
  * Constructor for FSEditLog. Underlying journals are constructed, but
  * no streams are opened until open() is called.
  *
  * @param conf The namenode configuration
  * @param storage Storage object used by namenode
  * @param editsDirs List of journals to use
  */
  FSEditLog(Configuration conf, NNStorage storage, List<URI> editsDirs) {
    isSyncRunning = false;
    this.conf = conf;
this.storage = storage;
// 在 format 阶段,metrics 的值为 null
    metrics = NameNode.getNameNodeMetrics();
    lastPrintTime = now();
    // If this list is empty, an error will be thrown on first use
    // of the editlog, as no journals will exist
    this.editsDirs = Lists.newArrayList(editsDirs);
    this.sharedEditsDirs = FSNamesystem.getSharedEditsDirs(conf);
  }

在创建完了 FSEditLog 和 NNStorageRetentionManager 对象后,FSIamge 的构造方法执行完毕,回到 NameNode 的 format 方法中。接下来就是要根据 FSImage 对象创建 FSNamesystem,前面曾提到 FSNamesystem 为 DataNode 执行实际的簿记工作,实际执行的该类的构造方法如下,其中 ignoreRetryCache 的值为 false:

/**
  * Create an FSNamesystem associated with the specified image.
  *
  * Note that this does not load any data off of disk — if you would
  * like that behavior, use {@link #loadFromDisk(Configuration)}
  *
  * @param conf configuration
  * @param fsImage The FSImage to associate with
  * @param ignoreRetryCache Whether or not should ignore the retry cache setup
  *                        step. For Secondary NN this should be set to true.
  * @throws IOException on bad configuration
  */
  FSNamesystem(Configuration conf, FSImage fsImage, boolean ignoreRetryCache)
      throws IOException

由于该构造方法代码比较多,就不贴出来了。可以概括为在该构造方法中,实例化了诸如 BlockManager、DatanodeStatistics、FSDirectory、CacheManager 等对象,读取了配置文件中的一些信息(后面计划专门研究该类)。在创建完毕 FSNamesystem 对象后,执行的是 FSEditLog 的 initJournalsForWrite()方法,该方法的代码如下:

private State state = State.UNINITIALIZED;
public synchronized void initJournalsForWrite() {
    Preconditions.checkState(state == State.UNINITIALIZED ||
        state == State.CLOSED, “Unexpected state: %s”, state);
    initJournals(this.editsDirs);
    state = State.BETWEEN_LOG_SEGMENTS;
  }

在该方法中先检查日志的状态,FSEditLog 刚创建时的状态为 UNINITIALIZED,执行完 initJournals()方法后日志的状态为 BETWEEN_LOG_SEGMENTS,意味日志还未打开。日志的初始化具体由 initJournals()完成,该方法的代码如下:

private synchronized void initJournals(List<URI> dirs) {
    int minimumRedundantJournals = conf.getInt(
        DFSConfigKeys.DFS_NAMENODE_EDITS_DIR_MINIMUM_KEY,
        DFSConfigKeys.DFS_NAMENODE_EDITS_DIR_MINIMUM_DEFAULT);
// 管理日志集合的对象
    journalSet = new JournalSet(minimumRedundantJournals);

    for (URI u : dirs) {
      boolean required = FSNamesystem.getRequiredNamespaceEditsDirs(conf)
          .contains(u);
      if (u.getScheme().equals(NNStorage.LOCAL_URI_SCHEME)) {
        StorageDirectory sd = storage.getStorageDirectory(u);
        if (sd != null) {
          journalSet.add(new FileJournalManager(conf, sd, storage),
              required, sharedEditsDirs.contains(u));
        }
      } else {
        journalSet.add(createJournal(u), required,
            sharedEditsDirs.contains(u));
      }
    }
 
    if (journalSet.isEmpty()) {
      LOG.error(“No edits directories configured!”);
    }
  }

该方法根据传递的 目录集合创建FileJournalManager 对象,并添加到 JournalSet 对象中,其中一个 FileJournalManager 对象管理一个保存 edits 文件的目录。初始化 edits 文件后,接下来就是对 fsimage 进行格式化了,具体代码为:

void format(FSNamesystem fsn, String clusterId) throws IOException {
    long fileCount = fsn.getTotalFiles();
    // Expect 1 file, which is the root inode
    Preconditions.checkState(fileCount == 1,
        “FSImage.format should be called with an uninitialized namesystem, has ” +
        fileCount + ” files”);
    NamespaceInfo ns = NNStorage.newNamespaceInfo();
    LOG.info(“Allocated new BlockPoolId: ” + ns.getBlockPoolID());
    ns.clusterID = clusterId;
   
    storage.format(ns);
    editLog.formatNonFileJournals(ns);
    saveFSImageInAllDirs(fsn, 0);
  }

在该代码中实际执行创建 fsimage 文件的代码为最后一行的 saveFSImageInAllDirs(fsn,0),该方法将实际的工作委托给下面的方法:

saveFSImageInAllDirs(source, NameNodeFile.IMAGE, txid, null);

在该方法中会根据保存 fsimage 的目录的个数创建与之相等的线程,这些线程完成实际的创建 fsimage 的任务。最后会清理旧的 edits 和检查点文件。

通过上面的分析可以发现,在执行 hdfs namenode –format 时仅创建了 fsimage 文件,并没有创建 edits 文件,但已经创建了相关对象。这一点也可以在执行完 format 后在本地文件系统中确认,目录中只有 fsimage 文件。

更多 Hadoop 相关信息见Hadoop 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=13

在 Hadoop 中 fsimage 保存最新的检查点信息,edits 保存自最新检查点后的命名空间的变化。在分析 hdfs namenode–format 的源代码时,已经明确了该过程根据配置文件的信息创建 fsimage 和 edits 文件,这篇文章具体分析一下创建 fsimage 和 edits 文件的源代码。在 NameNode 的 format 方法中,有如下的代码:

FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat);
    try {
      FSNamesystem fsn = new FSNamesystem(conf, fsImage);
      fsImage.getEditLog().initJournalsForWrite();

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

      fsImage.format(fsn, clusterId);
    } catch (IOException ioe) {
      LOG.warn(“Encountered exception during format: “, ioe);
      fsImage.close();
      throw ioe;
    }

在这段代码中主要涉及到了三个类,分别为 FSImage、FSNamesystem 和 FSEditLog,其中 FSImage 负责检查点,FSEditLog 维护命名空间变动的日志,FSNamesystem 为 DataNode 执行实际的簿记工作。创建 fsImage 对象的源代码为

/**
  * Construct the FSImage. Set the default checkpoint directories.
  *
  * Setup storage and initialize the edit log.
  *
  * @param conf Configuration
  * @param imageDirs Directories the image can be stored in.
  * @param editsDirs Directories the editlog can be stored in.
  * @throws IOException if directories are invalid.
  */
  protected FSImage(Configuration conf,Collection<URI> imageDirs,
                    List<URI> editsDirs)throws IOException {
this.conf = conf;
/* NNStorage 负责管理 NameNode 使用的 StorageDirectories*/
storage = new NNStorage(conf, imageDirs, editsDirs);
/* 根据 dfs.namenode.name.dir.restore 的值决定是否尝试重新存储失败的存储目录
* 默认值为 false
*/
    if(conf.getBoolean(DFSConfigKeys.DFS_NAMENODE_NAME_DIR_RESTORE_KEY,
                      DFSConfigKeys.DFS_NAMENODE_NAME_DIR_RESTORE_DEFAULT)) {
      storage.setRestoreFailedStorage(true);
    }
this.editLog = new FSEditLog (conf, storage, editsDirs);
/*NNStorageRetentionManager 负责检查 NameNode 的存储目录,
    * 并在 fsimage 和 edits 文件上执行保留策略。
*/
    archivalManager = new NNStorageRetentionManager(conf, storage, editLog);
  }

FSImage 的构造方法中,创建了 NNStorage、FSEditLog 和 NNStorageRetentionManager 对象,NNStorage 的构造方法源代码如下:

public NNStorage(Configuration conf, Collection<URI> imageDirs, Collection<URI> editsDirs) throws IOException {
    super(NodeType.NAME_NODE);
    storageDirs = new CopyOnWriteArrayList<StorageDirectory>();
   
    // this may modify the editsDirs, so copy before passing in
    setStorageDirectories(imageDirs,
                          Lists.newArrayList(editsDirs),
                          FSNamesystem.getSharedEditsDirs(conf));
  }

NNStorage 中的 setStorageDirectories 方法用于初始化存储 fsimage 和 edits 文件的目录。这里不分析该方法的全部源代码,主要分析初始化 fsimage 的部分,如下:

// Add all name dirs with appropriate NameNodeDirType
    for (URI dirName : fsNameDirs) {
      checkSchemeConsistency(dirName);
      boolean isAlsoEdits = false;
      for (URI editsDirName : fsEditsDirs) {
        if (editsDirName.compareTo(dirName) == 0) {
          isAlsoEdits = true;
          fsEditsDirs.remove(editsDirName);
          break;
        }
      }
      NameNodeDirType dirType = (isAlsoEdits) ?
                          NameNodeDirType.IMAGE_AND_EDITS :
                          NameNodeDirType.IMAGE;
      // Add to the list of storage directories, only if the
      // URI is of type file://
      if(dirName.getScheme().compareTo(“file”) == 0) {
        this.addStorageDir(new StorageDirectory(new File(dirName.getPath()),
            dirType,
            sharedEditsDirs.contains(dirName))); // Don’t lock the dir if it’s shared.
      }
    }

Ubuntu 13.04 上搭建 Hadoop 环境 http://www.linuxidc.com/Linux/2013-06/86106.htm

Ubuntu 12.10 +Hadoop 1.2.1 版本集群配置 http://www.linuxidc.com/Linux/2013-09/90600.htm

Ubuntu 上搭建 Hadoop 环境(单机模式 + 伪分布模式)http://www.linuxidc.com/Linux/2013-01/77681.htm

Ubuntu 下 Hadoop 环境的配置 http://www.linuxidc.com/Linux/2012-11/74539.htm

单机版搭建 Hadoop 环境图文教程详解 http://www.linuxidc.com/Linux/2012-02/53927.htm

搭建 Hadoop 环境(在 Winodws 环境下用虚拟机虚拟两个 Ubuntu 系统进行搭建)http://www.linuxidc.com/Linux/2011-12/48894.htm

更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2014-09/107139p2.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计10766字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中