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

在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.
      }
    }

在该段代码中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文件。

时间: 2024-08-29 22:51:15

Hadoop-2.4.1学习之创建fsimage和edits源码分析的相关文章

Activity的创建和显示以及源码分析记录

Tips:此源码分析基于Android 4.2 先来看看一个Activity上的UI控件结构: 图1-1 Activity中的UI组件结构 好了现在开始分析...... 一.Activity的创建 了解android的zygote分裂你会知道,每个APP都是zygote的子进程,而他的入口函数是ActivityThread类中的main函数.其中有一个handleLaucherActivity函数,这里就是 创建Activity的地方. private void handleLaunchActi

大数据学习笔记2--hdfs工作原理及源码分析

windows下配置hadoop hadoop 安装包解压,路径不要有特殊字符 lib和bin直接解压出来的不可用,需要自己重新编译 配置环境变量:HADOOP_HOME,path中添加:bin目录 namenode 整个文件系统的管理节点.它维护着整个文件系统的文件目录树,文件/目录的元信息和每个文件对应的数据块列表.接收用户的操作请求. 响应客户端的请求,上传文件: client申请上传文件,namenode查看元数据信息,查看客户端申请的路径是否已存在 namenode返回可用的datan

[原创]java WEB学习笔记70:Struts2 学习之路-- struts2拦截器源码分析,运行流程

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

(转)Bootstrap 之 Metronic 模板的学习之路 - (4)源码分析之脚本部分

https://segmentfault.com/a/1190000006709967 上篇我们将 body 标签主体部分进行了简单总览,下面看看最后的脚本部门. 页面结尾部分(Javascripts 脚本文件) 我们来看看代码最后的代码,摘取如下: <!--[if lt IE 9]> <script src="../assets/global/plugins/respond.min.js"></script> <script src=&quo

(转)Bootstrap 之 Metronic 模板的学习之路 - (3)源码分析之 body 部分

https://segmentfault.com/a/1190000006697252 body 的组成结构 body 部分包含了 HEADER.CONTAINER.FOOTER,其中 CONTAINER 部分又包含了 SIDEBAR.CONTENT.QUICK SIDEBAR 几个部分.body部分源码折叠后截图如下: Header 页面顶部 Header contains of logo and top menu bar and it used in all pages. 页面顶部(或头部)

Docker源码分析(五):Docker Server的创建

1.Docker Server简介 Docker架构中,Docker Server是Docker Daemon的重要组成部分.Docker Server最主要的功能是:接受用户通过Docker Client发送的请求,并按照相应的路由规则实现路由分发. 同时,Docker Server具备十分优秀的用户友好性,多种通信协议的支持大大降低Docker用户使用Docker的门槛.除此之外,Docker Server设计实现了详尽清晰的API接口,以供Docker用户选择使用.通信安全方面,Docke

Hadoop-2.4.1学习之NameNode -format源码分析

在Hadoop-2.X中,使用hdfs namenode –format对文件系统进行格式化.虽然无论是在生产环境还是测试环境中,已经使用了该命令若干次了,也大体了解该命令就是在本地文件系统中创建几个文件夹,但具体是如何执行的则需要通过阅读源代码来了解了. 要想看到该命令的源代码,需要看看hdfs脚本中是如何执行相应的java类的.在hdfs脚本中,下面的语句说明了实际执行的java类和参数,其中类为org.apache.hadoop.hdfs.server.namenode.NameNode,

Hadoop之HDFS原理及文件上传下载源码分析(上)

HDFS原理 首先说明下,hadoop的各种搭建方式不再介绍,相信各位玩hadoop的同学随便都能搭出来. 楼主的环境: 操作系统:Ubuntu 15.10 hadoop版本:2.7.3 HA:否(随便搭了个伪分布式) 文件上传 下图描述了Client向HDFS上传一个200M大小的日志文件的大致过程: 首先,Client发起文件上传请求,即通过RPC与NameNode建立通讯. NameNode与各DataNode使用心跳机制来获取DataNode信息.NameNode收到Client请求后,

细水长流Hadoop源码分析(3)RPC Server初始化构造

声明:个人原创,转载请注明出处.文中引用了一些网上或书里的资料,如有不妥之处请告之. 本文是我阅读Hadoop 0.20.2第二遍时写的笔记,在阅读过程中碰到很多问题,最终通过各种途径解决了大部分.Hadoop整个系统设计精良,源码值得学习分布式的同学们阅读,以后会将所有笔记一一贴出,希望能方便大家阅读源码,少走弯路. 目录 4 RPC服务器(org.apache.hadoop,ipc.Server) 4.1 服务器初始化 4 RPC服务器(org.apache.hadoop,ipc.Serve