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

Hadoop1.x和2.X的HDFS fsimage和edits文件运行机制对比

109次阅读
没有评论

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

一、概述

之前写过一篇非常详细的, 利用 QJM 在 HDFS2.0 部署 HA 策略的文章,主要说了利用 QJM 进行 HA 部署以及其原理(http://www.linuxidc.com/Linux/2014-10/107933.htm)。但是,其中没有详细描述 Hadoop2.x 通过 QJM 部署 HA 完毕之后,ActiveNamenode 和 StandbyNamenode 之间的元数据运行机制, 实际上由于 2.x 的 HA 策略的引入,其元数据的运行机制和 1.x 比起来已经有了很大的不同。写这篇 blog 的目的主要是为了对 hadoop1.x 和 hadoop2.x 的元数据运行机制进行比较,当是自己的笔记吧。

二、fsimage 和 edits 文件的作用

    先来看看关于 NameNode 元数据相关的目录结构,也就是配置在 hdfs-site.xml 上的 dfs.name.dir 项,具体目录为 $dfs.name.dir/current。看看目录(hadoop2.2.0 版本):

Hadoop1.x 和 2.X 的 HDFS fsimage 和 edits 文件运行机制对比

我们发现有些以 edites_开头和少量以 fsimage 开头的文件。fsimage 和 edites 文件都是 hadoop 文件系统元数据的组成部分。

    其中 fsimage 镜像文件包含了整个 HDFS 文件系统的所有目录和文件的 indoe 信息。对于文件来说包括了数据块描述信息、修改时间、访问时间等;对于目录来说包括修改时间、访问权限控制信息 (目录所属用户,所在组等) 等。

    另外,edit 文件主要是在 NameNode 已经启动情况下对 HDFS 进行的各种更新操作进行记录,HDFS 客户端执行所有的写操作都会被记录到 edit 文件中。

————————————– 分割线 ————————————–

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 中 HDFS 和 MapReduce 节点基本简介 http://www.linuxidc.com/Linux/2013-09/89653.htm

《Hadoop 实战》中文版 + 英文文字版 + 源码【PDF】http://www.linuxidc.com/Linux/2012-10/71901.htm

Hadoop: The Definitive Guide【PDF 版】http://www.linuxidc.com/Linux/2012-01/51182.htm

————————————– 分割线 ————————————–

三、NameNode 简单启动过程

    在 HDFS 中,任何一个文件,目录和 block,在 HDFS 中都会被表示为一个 object 存储在 namenode 的内存中,每一个 object 占用 150 bytes 的内存空间。当 NameNode 启动的时候,首先会将 fsimage 里面的所有内容映像到内存中,然后再一条一条地执行 edits 中的记录,然后等待各个 Datanode 向自己汇报块的信息来组装 blockMap,从而离开安全模式。在这里涉及到 BlockMap 结构,所谓的 BlockMap 结构就是记录着 block 的元数据(加载在 NameNode 的内存中)和其对应的实际数据(存储在各个 DataNode 中)的映射关系。真正每个 block 对应到 datanodes 列表的信息在 hadoop 中并没有进行持久化存储,而是在所有 datanode 启动时,每个 datanode 对本地磁盘进行扫描,将本 datanode 上保存的 block 信息汇报给 namenode,namenode 在接收到每个 datanode 的块信息汇报后,将接收到的块信息,以及其所在的 datanode 信息等保存在内存中。HDFS 就是通过这种块信息汇报的方式来完成 block -> datanodes list 的对应表构建。Datanode 向 namenode 汇报块信息的过程叫做 blockReport,而 namenode 将 block -> datanodes list 的对应表信息保存在一个叫 BlocksMap 的数据结构中。因此,我们可以得出一个非常重要的结论,NameNode 不会定期的向各个 DataNode 去”索取“块的信息,而是各个 datanode 定期向 namenode 汇报块的信息。当组装完 NameNode 组装完 BlockMap 的信息后基本上整个 HDFS 的启动就完成了,可以顺利地离开安全模式了。分析到这里,我们就可以很清楚地知道整个 HDFS 的启动速度是由上面决定的了,第一:执行各个 edits 文件,这个也是我这篇 blog 重点讨论的。第二:各个 DataNode 向 NameNode 汇报块信息的进度(当 99.9% 的 block 汇报完毕才会离开安全模式)。

四、Hadoop1.x 中 fsimage 和 edits 的合并机制

    当 edits 文件很多很大的时候,NameNode 在启动的时候需要逐一每条的执行这些 edits 文件,这就严重地影响了整个 HDFS 的启动时间。这问题在 hadoop1.x 是通过 SecondaryNamenode 机制将 edits 文件合并到 fsimage 中,其之得到解决,SecondaryNamenode 在第一代的 Hadoop 中算是一个非热备的 NameNode 备份。整个 SecondaryNamenode 的工作流程简单地画了一下图:

Hadoop1.x 和 2.X 的 HDFS fsimage 和 edits 文件运行机制对比

 

简单描述一下具体流程:

步骤一:SSN 在一个 checkpoint 时间点和 NameNode 进行通信,请求 NameNode 停止使用 edits 文件记录相关操作而是暂时将新的 Write 操作写到新的文件 edit.new 来。

步骤二:SSN 通过 HTTP GET 的方式从 NameNode 中将 fsimage 和 edits 文件下载回来本地目录中。

步骤三:SSN 中合并 edits 和 fsimage。SSN 将从 NameNode 中下载回来的 fsimage 加载到内存中,然后逐条 执行 edits 文件中的各个操作项,使得加载到内存中的 fsimage 中包含 edits 中的操作,这个过程就是所谓的合并了。

步骤四:在 SSN 中合并完 fsimage 和 edits 文件后,需要将新的 fsimage 回传到 NameNode 上,这个是通过 HTTP POST 方式进行的。

步骤五:NameNode 将从 SSN 接收到的新的 fsimage 替换掉旧的 fsimage。同时将 edits.new 文件转换为通常的 edits 文件,这样 edits 文件的大小就得到减少了。SSN 整个合并以及和 NameNode 的交互过程到这里已经结束。

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

五、Hadoop2.x 中 fsimage 和 edits 的合并机制

(1)Hadoop2.x 的 HA 策略简介

    由于 HDFS2.0 的 HA 策略的加入,使得在 hadoop2.x 中的 fsimage 和 edits 的合并机制和 hadoop1.x 完全不同。在 hadoop2.x 中已经没有 SecondaryNamenode,而是直接通过 QJM 方式配置若干奇数个 JournalNode 来实现 NameNode 热备 HA 策略。详细的 Hadoop2.x 的 HA 策略的原理和部署这里就不说了,可以看我之前的 blog:http://www.linuxidc.com/Linux/2014-10/107933.htm。这里主要说说简单的 HA 机制以及其工作流程。在同一个集群当中同时运行着 2 个 Namenode,一个处于 Active 状态,用于处理客户端的请求。另外一个处于 standy 状态,用于热备,其状态和 active Namenode 是维持一致的,当 Active Namenode 出现故障,Standy Namenode 可以马上转化为 Active Namenode。但是 2 个 Namenode 中有且只有一个处于 active 状态来处理客户端的请求,否则将会产生脑裂情况。这样看来,那么客户端的一次写请求,其操作日志需要同时被记录再 Active NameNode 和 standy NameNode 中。那么疑问产生了,在保证不产生脑裂的情况下如何使得操作日志需要同时被记录再 Active NameNode 和 standy NameNode 呢?

    为了让 Standby NameNode 的状态和 Active NameNode 保持同步,即元数据保持一致,它们都将会和 JournalNodes 守护进程通信。当 Active NameNode 执行任何有关命名空间的修改,它至少需要将产生的 edits 持久化到 N -((N-1)/2)个 JournalNodes 上才能保证命名空间修改的安全性,换句话说:如果你的 HA 策略中启动了 N 个 JournalNode 进程那么整个 QJM 最多允许(N-1)/ 2 个进程死掉,这样才能保证 editLog 成功完整地被写入。比如 3 个 JournalNode 时,最多允许 1 个 JournalNode 挂掉,5 个 JournalNode 时,最多允许 2 个 JournalNode 挂掉。而 Standby NameNode 负责观察 edits log 的变化,它能够读取从 JNs 中读取 edits 信息,并更新其内部的命名空间。一旦 Active NameNode 出现故障,Standby NameNode 将会保证从 JNs 中读出了全部的 Edits,然后切换成 Active 状态。Standby NameNode 读取全部的 edits 可确保发生故障转移之前,是和 Active NameNode 拥有完全同步的命名空间状态。

(2)Hadoop2.x 中 fsimage 和 edits 的合并流程

步骤一:Active Namenode 和 Standby NameNode 从 JournalNodes 的 edits 共享目录中同步 edits 到自己 edits 目录中。其中 JournalNodes 的 edits 共享目录的共享目录在配置 HA 策略的时候由下面参数配置:

<property>

<name>dfs.namenode.shared.edits.dir</name>

<value>qjournal://XX/xxcluster</value>

</property>

<property>

<name>dfs.journalnode.edits.dir</name>

<value>/journalNode/edits</value>

</property>

步骤二:Standby NameNode 定期检查合并的条件是否成立,如果成立会合并 fsimage 和 edits 文件;

    在 Standby NameNode 中会一直维护着一个叫 CheckpointerThread 的线程,这个线程调用 StandbyCheckpointer 类去每隔 1000*Math.min(checkpointCheckPeriod, checkpointPeriod)秒检测一次是否要将 fsimage 和从 journalNode 同步过来的 edits 做一次合并操作,其中 checkpointCheckPeriod 由 hdfs-site.xml 中的 dfs.namenode.checkpoint.period 配置,checkpointPeriod 则有 hdfs-site.xml 中的 dfs.namenode.checkpoint.check.period 配置。

<property>

  <name>dfs.namenode.checkpoint.period</name>

  <value>3600</value>

  <description>The number of seconds between two periodic checkpoints.

  </description>

</property>

<property>

  <name>dfs.namenode.checkpoint.check.period</name>

  <value>60</value>

  <description>The SecondaryNameNode and CheckpointNode will poll the NameNode

  every ‘dfs.namenode.checkpoint.check.period’ seconds to query the number

  of uncheckpointed transactions.

  </description>

</property>

其中具体什么条件才符合合并条件,我们就看看看 StandbyCheckpointer 类的 dowork 方法,看我的注释就一目了然了:

 private void doWork() {

      // Reset checkpoint time so that we don’t always checkpoint

      // on startup.

      lastCheckpointTime = now();

      while (shouldRun) {

        try {

        // 每隔 1000*Math.min(checkpointCheckPeriod, checkpointPeriod)秒检测一次是否要将 fsimage 和从 journalNode 同步过来的 edits 做一次合并操作

          Thread.sleep(1000 * checkpointConf.getCheckPeriod());

        } catch (InterruptedException ie) {

        }

        if (!shouldRun) {

          break;

        }

        try {

          // We may have lost our ticket since last checkpoint, log in again, just in case

          if (UserGroupInformation.isSecurityEnabled()) {

            UserGroupInformation.getCurrentUser().checkTGTAndReloginFromKeytab();

          }

         

          long now = now();

          // 获得最后一次往 journalNode 写入的 TxId(这个可以在 namenode 日志或者 50070 界面可以看到)和最近一次做 Checkpoint 的 TxId 的差值

          long uncheckpointed = countUncheckpointedTxns();

          long secsSinceLast = (now – lastCheckpointTime)/1000;

         

          boolean needCheckpoint = false;

          // 第一种符合合并的情况:当最后一次往 journalNode 写入的 TxId(这个可以在 namenode 日志或者 50070 界面可以看到)

          // 和最近一次做 Checkpoint 的 TxId 的差值大于或者等于 dfs.namenode.checkpoint.txns 配置的数量(默认 1000000)时做一次合并

          if (uncheckpointed >= checkpointConf.getTxnCount()) {

            LOG.info(“Triggering checkpoint because there have been ” +

                uncheckpointed + ” txns since the last checkpoint, which ” +

                “exceeds the configured threshold ” +

                checkpointConf.getTxnCount());

            needCheckpoint = true;

          }

          // 第二种符合合并的情况:当时间间隔大于或者等于 dfs.namenode.checkpoint.period 配置的时间是做合并

          else if (secsSinceLast >= checkpointConf.getPeriod()) {

            LOG.info(“Triggering checkpoint because it has been ” +

                secsSinceLast + ” seconds since the last checkpoint, which ” +

                “exceeds the configured interval ” + checkpointConf.getPeriod());

            needCheckpoint = true;

          }

         

          synchronized (cancelLock) {

            if (now < preventCheckpointsUntil) {

              LOG.info(“But skipping this checkpoint since we are about to failover!”);

              canceledCount++;

              continue;

            }

            assert canceler == null;

            canceler = new Canceler();

          }

         

          if (needCheckpoint) {

            doCheckpoint();

            lastCheckpointTime = now;

          }

        } catch (SaveNamespaceCancelledException ce) {

          LOG.info(“Checkpoint was cancelled: ” + ce.getMessage());

          canceledCount++;

        } catch (InterruptedException ie) {

          // Probably requested shutdown.

          continue;

        } catch (Throwable t) {

          LOG.error(“Exception in doCheckpoint”, t);

        } finally {

          synchronized (cancelLock) {

            canceler = null;

          }

        }

      }

    }

  }

步骤三:Standby NameNode 中的 StandbyCheckpointer 类合并完 fsimage 和 edits 之后,将合并之后的 fsimage 上传到 Active NameNode 相应目录中;

步骤四:Active NameNode 接到最新的 fsimage 文件之后,替换掉旧的 fsimage 和清理掉 edits 文件;到这里整个合并过程已经完毕。

五、总结

    本文主要做了 hadoop1.x 和 hadoop2.x 的 fsimage 和 edits 文件合并机制的对比,另外也对 hadoop2.x 的 HA 机制做了简单的介绍。写完这边 blog 下来自己对 SSN 以及 hadoop2.x 的 edits 文件的处理有了更深入清晰的认识;另外通过这样的对比,感觉自己收获最大的是对整个 HDFS 的启动过程有很深入的认识。

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

一、概述

之前写过一篇非常详细的, 利用 QJM 在 HDFS2.0 部署 HA 策略的文章,主要说了利用 QJM 进行 HA 部署以及其原理(http://www.linuxidc.com/Linux/2014-10/107933.htm)。但是,其中没有详细描述 Hadoop2.x 通过 QJM 部署 HA 完毕之后,ActiveNamenode 和 StandbyNamenode 之间的元数据运行机制, 实际上由于 2.x 的 HA 策略的引入,其元数据的运行机制和 1.x 比起来已经有了很大的不同。写这篇 blog 的目的主要是为了对 hadoop1.x 和 hadoop2.x 的元数据运行机制进行比较,当是自己的笔记吧。

二、fsimage 和 edits 文件的作用

    先来看看关于 NameNode 元数据相关的目录结构,也就是配置在 hdfs-site.xml 上的 dfs.name.dir 项,具体目录为 $dfs.name.dir/current。看看目录(hadoop2.2.0 版本):

Hadoop1.x 和 2.X 的 HDFS fsimage 和 edits 文件运行机制对比

我们发现有些以 edites_开头和少量以 fsimage 开头的文件。fsimage 和 edites 文件都是 hadoop 文件系统元数据的组成部分。

    其中 fsimage 镜像文件包含了整个 HDFS 文件系统的所有目录和文件的 indoe 信息。对于文件来说包括了数据块描述信息、修改时间、访问时间等;对于目录来说包括修改时间、访问权限控制信息 (目录所属用户,所在组等) 等。

    另外,edit 文件主要是在 NameNode 已经启动情况下对 HDFS 进行的各种更新操作进行记录,HDFS 客户端执行所有的写操作都会被记录到 edit 文件中。

————————————– 分割线 ————————————–

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 中 HDFS 和 MapReduce 节点基本简介 http://www.linuxidc.com/Linux/2013-09/89653.htm

《Hadoop 实战》中文版 + 英文文字版 + 源码【PDF】http://www.linuxidc.com/Linux/2012-10/71901.htm

Hadoop: The Definitive Guide【PDF 版】http://www.linuxidc.com/Linux/2012-01/51182.htm

————————————– 分割线 ————————————–

三、NameNode 简单启动过程

    在 HDFS 中,任何一个文件,目录和 block,在 HDFS 中都会被表示为一个 object 存储在 namenode 的内存中,每一个 object 占用 150 bytes 的内存空间。当 NameNode 启动的时候,首先会将 fsimage 里面的所有内容映像到内存中,然后再一条一条地执行 edits 中的记录,然后等待各个 Datanode 向自己汇报块的信息来组装 blockMap,从而离开安全模式。在这里涉及到 BlockMap 结构,所谓的 BlockMap 结构就是记录着 block 的元数据(加载在 NameNode 的内存中)和其对应的实际数据(存储在各个 DataNode 中)的映射关系。真正每个 block 对应到 datanodes 列表的信息在 hadoop 中并没有进行持久化存储,而是在所有 datanode 启动时,每个 datanode 对本地磁盘进行扫描,将本 datanode 上保存的 block 信息汇报给 namenode,namenode 在接收到每个 datanode 的块信息汇报后,将接收到的块信息,以及其所在的 datanode 信息等保存在内存中。HDFS 就是通过这种块信息汇报的方式来完成 block -> datanodes list 的对应表构建。Datanode 向 namenode 汇报块信息的过程叫做 blockReport,而 namenode 将 block -> datanodes list 的对应表信息保存在一个叫 BlocksMap 的数据结构中。因此,我们可以得出一个非常重要的结论,NameNode 不会定期的向各个 DataNode 去”索取“块的信息,而是各个 datanode 定期向 namenode 汇报块的信息。当组装完 NameNode 组装完 BlockMap 的信息后基本上整个 HDFS 的启动就完成了,可以顺利地离开安全模式了。分析到这里,我们就可以很清楚地知道整个 HDFS 的启动速度是由上面决定的了,第一:执行各个 edits 文件,这个也是我这篇 blog 重点讨论的。第二:各个 DataNode 向 NameNode 汇报块信息的进度(当 99.9% 的 block 汇报完毕才会离开安全模式)。

四、Hadoop1.x 中 fsimage 和 edits 的合并机制

    当 edits 文件很多很大的时候,NameNode 在启动的时候需要逐一每条的执行这些 edits 文件,这就严重地影响了整个 HDFS 的启动时间。这问题在 hadoop1.x 是通过 SecondaryNamenode 机制将 edits 文件合并到 fsimage 中,其之得到解决,SecondaryNamenode 在第一代的 Hadoop 中算是一个非热备的 NameNode 备份。整个 SecondaryNamenode 的工作流程简单地画了一下图:

Hadoop1.x 和 2.X 的 HDFS fsimage 和 edits 文件运行机制对比

 

简单描述一下具体流程:

步骤一:SSN 在一个 checkpoint 时间点和 NameNode 进行通信,请求 NameNode 停止使用 edits 文件记录相关操作而是暂时将新的 Write 操作写到新的文件 edit.new 来。

步骤二:SSN 通过 HTTP GET 的方式从 NameNode 中将 fsimage 和 edits 文件下载回来本地目录中。

步骤三:SSN 中合并 edits 和 fsimage。SSN 将从 NameNode 中下载回来的 fsimage 加载到内存中,然后逐条 执行 edits 文件中的各个操作项,使得加载到内存中的 fsimage 中包含 edits 中的操作,这个过程就是所谓的合并了。

步骤四:在 SSN 中合并完 fsimage 和 edits 文件后,需要将新的 fsimage 回传到 NameNode 上,这个是通过 HTTP POST 方式进行的。

步骤五:NameNode 将从 SSN 接收到的新的 fsimage 替换掉旧的 fsimage。同时将 edits.new 文件转换为通常的 edits 文件,这样 edits 文件的大小就得到减少了。SSN 整个合并以及和 NameNode 的交互过程到这里已经结束。

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

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