设为首页 收藏本站
查看: 1091|回复: 0

[经验分享] Hadoop1.x和2.X的HDFS fsimage和edits文件运行机制对比

[复制链接]

尚未签到

发表于 2018-10-30 13:36:24 | 显示全部楼层 |阅读模式
  一、概述
  之前写过一篇非常详细的,利用QJM在HDFS2.0部署HA策略的文章,主要说了利用QJM进行HA部署以及其原理(http://zengzhaozheng.blog.51cto.com/8219051/1441170 )。但是,其中没有详细描述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版本):
DSC0000.jpg

  我们发现有些以edites_开头和少量以fsimage开头的文件。fsimage和edites文件都是hadoop文件系统元数据的组成部分。
  其中fsimage镜像文件包含了整个HDFS文件系统的所有目录和文件的indoe信息。对于文件来说包括了数据块描述信息、修改时间、访问时间等;对于目录来说包括修改时间、访问权限控制信息(目录所属用户,所在组等)等。
  另外,edit文件主要是在NameNode已经启动情况下对HDFS进行的各种更新操作进行记录,HDFS客户端执行所有的写操作都会被记录到edit文件中。
  三、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的工作流程简单地画了一下图:
DSC0001.jpg

  简单描述一下具体流程:
  步骤一: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的交互过程到这里已经结束。
  五、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://zengzhaozheng.blog.51cto.com/8219051/1441170 。这里主要说说简单的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策略的时候由下面参数配置:
  
  dfs.namenode.shared.edits.dir
  
  qjournal://XX/xxcluster
  

  

  
  dfs.journalnode.edits.dir
  
  /journalNode/edits
  

  步骤二: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 配置。
  
  dfs.namenode.checkpoint.period
  
  3600
  
  The number of seconds between two periodic checkpoints.
  
  
  

  

  
  dfs.namenode.checkpoint.check.period
  
  60
  
  The SecondaryNameNode and CheckpointNode will poll the NameNode
  
  every 'dfs.namenode.checkpoint.check.period' seconds to query the number
  
  of uncheckpointed transactions.
  
  
  

  其中具体什么条件才符合合并条件,我们就看看看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的启动过程有很深入的认识。
  转载请注明出处:http://zengzhaozheng.blog.51cto.com/8219051/1561591



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-628569-1-1.html 上篇帖子: pig安装在hadoop伪分布式节点 下篇帖子: 【电子书】Hadoop实战手册 (样章第一章)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表