美文网首页
hdfs namenode 启动流程进入安全模式条件

hdfs namenode 启动流程进入安全模式条件

作者: 邵红晓 | 来源:发表于2021-08-31 14:28 被阅读0次

namenode启动流程

FSNamesystem.java

 void startCommonServices(Configuration conf, HAContext haContext) throws IOException {
    this.registerMBean(); // register the MBean for the FSNamesystemState
    writeLock();
    this.haContext = haContext;
    try {

      /**
       * hadoop namenode  -> fsimage + editLog(磁盘) -> 存储资源是否够?100m
       */
      //NameNode资源检查 通过core-site.xml  hdfs-site.xml两个文件,就知道了元数据存在哪儿?
      //(1)NameNode的两个目录:存储fsiamge的目录,存储editlog的目录。
        // 但是一般情况下,或者默认情况这两个使用的是同一个目录。
      //加载了配置文件,配置文件里面有存储元数据的目录。
      nnResourceChecker = new NameNodeResourceChecker(conf);
      //TODO 检查是否有足够的磁盘存储元数据
      checkAvailableResources();

      assert safeMode != null && !isPopulatingReplQueues();
      StartupProgress prog = NameNode.getStartupProgress();
      prog.beginPhase(Phase.SAFEMODE);
      prog.setTotal(Phase.SAFEMODE, STEP_AWAITING_REPORTED_BLOCKS,
              getCompleteBlocksTotal());
      //TODO HDFS的安全模式
      setBlockTotal();
      //TODO 启动重要服务
      blockManager.activate(conf);
    } finally {
      writeUnlock();
    }
    
    registerMXBean();
    DefaultMetricsSystem.instance().register(this);
    if (inodeAttributeProvider != null) {
      inodeAttributeProvider.start();
      dir.setINodeAttributeProvider(inodeAttributeProvider);
    }
    snapshotManager.registerMXBean();
  }

  public void setBlockTotal() {
    // safeMode is volatile, and may be set to null at any time
    SafeModeInfo safeMode = this.safeMode;
    if (safeMode == null)
      return;
    //TODO 设置安全模式
    //getCompleteBlocksTotal()集群里面应该能正常使用的block的个数
    safeMode.setBlockTotal((int)getCompleteBlocksTotal());
  }
/**
   * Get the total number of COMPLETE blocks in the system.
   * For safe mode only complete blocks are counted
   * TODO 在HDFS集群里面block的状态分为两种类型:
   * 1)complete类型:正常的可用的block。
   * 2)underconstuction类型:处于正在构建的block
   * 返回去的就是历史所有已经complete状态的block的个数
   */
  private long getCompleteBlocksTotal() {
    // Calculate number of blocks under construction
    long numUCBlocks = 0;
    readLock();
    //获取所有正在构建的block
    numUCBlocks = leaseManager.getNumUnderConstructionBlocks();
    try {    //获取所有的block   -  正在构建的block = 应该能正常使用的总的block
      return getBlocksTotal() - numUCBlocks;
    } finally {
      readUnlock();
    }
  }

 /**
     * Set total number of blocks.
     * 
     * total:complete状态的block的个数,也就是我们正常的block的个数
     *
     * 1000 block   999 处于安全模式
     * 
     */
    private synchronized void setBlockTotal(int total) {//1000 block
      this.blockTotal = total;
      //TODO 计算阈值
      //1000 * 0.999  = 999
      this.blockThreshold = (int) (blockTotal * threshold);
      //999
      this.blockReplQueueThreshold = 
        (int) (blockTotal * replQueueThreshold);
      if (haEnabled) {
        // After we initialize the block count, any further namespace
        // modifications done while in safe mode need to keep track
        // of the number of total blocks in the system.
        this.shouldIncrementallyTrackBlocks = true;
      }
      if(blockSafe < 0)
        this.blockSafe = 0;
      //TODO 检查安全模式
      checkMode();
    }


   /** 
     * There is no need to enter safe mode 
     * if DFS is empty or {@link #threshold} == 0
     * 
     * TODO  条件一
     * threshold != 0 && blockSafe < blockThreshold
     *   HDFS的元数据那儿程序总计分析出来上一次关闭集群之前
     *   假设有1000个complete的block,默认是阈值的计算比例是0.999
     *   这样blockThreshold的值是999
     *   现在集群起来了以后,发现累计datanode汇报过来的complete的block个数(blockSafe)
     *   如果小于999就让集群处于安全模式。
     *
     * TODO 条件二
     *  datanodeThreshold != 0 && getNumLiveDataNodes() < datanodeThreshold
     *  如果存活的datanode的个数小于一定的数目的时候,也会进去安全模式
     *  默认是0,所以相当于没启用,但是我们也可以配置,如果存活的datanode个数
     *  少于多少就让HDFS集群出入安全模式。
     * TODO 条件三
     *  !nameNodeHasResourcesAvailable()
     *  就是前面 检查NameNode写的元数据的目录空间是否大于100M,
     *  如果目录的空间小于100M,nameNodeHasResourcesAvailable 就为false
     *  hdfs就会进入安全模式。
     */
    private boolean needEnter() {
       //999
      return (threshold != 0 && blockSafe < blockThreshold) ||
          //默认这条件是不生效的
              //100个节点,99
        (datanodeThreshold != 0 && getNumLiveDataNodes() < datanodeThreshold) ||
          //!false
        (!nameNodeHasResourcesAvailable());
    }

  /**
     * Increment number of safe blocks if current block has 
     * reached minimal replication.
     * @param replication current replication 
     */
    private synchronized void incrementSafeBlockCount(short replication) {
      if (replication == safeReplication) {
        //datanode会进行block的汇报 block信息 -> namenode
        //1000
        this.blockSafe++; //累计我们datanode汇报过来完整的block块

        // Report startup progress only if we haven't completed startup yet.
        StartupProgress prog = NameNode.getStartupProgress();
        if (prog.getStatus(Phase.SAFEMODE) != Status.COMPLETE) {
          if (this.awaitingReportedBlocksCounter == null) {
            this.awaitingReportedBlocksCounter = prog.getCounter(Phase.SAFEMODE,
              STEP_AWAITING_REPORTED_BLOCKS);
          }
          this.awaitingReportedBlocksCounter.increment();
        }

        checkMode();
      }
    }

总结

blockTotal=hdfs总块数
this.blockThreshold = (int) (blockTotal * threshold);
threshold=0.999
blockThreshold = 999
也就是只允许hdfs丢失一个块
条件
1、datanode上报的块个数少于blockTh reshold=0.999*total synchronized incrementSafeBlockCount()方法中 this.blockSafe++;
2、集群活跃节点少于 datanodethead 比如30个节点,挂了一个,直接进入安全模式,一般不使用,默认datanodethead=0
3、判断磁盘空间是否namenode写元数据的磁盘空间是否大于100m,如果小于就进入安全模式
一般是进入安全模式,就是数据块丢失了
注意:namenode-设置的datanode心跳超时时间是10min30s,为什么?
容错,场景是在datanode的副本补齐操作,占用大量网络带宽
4、元数据文件内容
fsimage文件内容

  <INodeDirectorySection>
        <directory>
            <parent>16385</parent>
            <inode>18543</inode>
            <inode>16474</inode>
            <inode>16419</inode>
            <inode>16417</inode>
            <inode>16427</inode>
            <inode>17544</inode>
            <inode>17561</inode>
        </directory>
        <directory>
            <parent>16417</parent>
            <inode>16420</inode>
        </directory>
        <directory>
            <parent>16419</parent>
            <inode>17399</inode>
            <inode>17258</inode>
            <inode>16418</inode>
            <inode>17294</inode>
        </directory>
         ......        // 省略其他<directory>标签
    </INodeDirectorySection>

相关文章

网友评论

      本文标题:hdfs namenode 启动流程进入安全模式条件

      本文链接:https://www.haomeiwen.com/subject/hdjziltx.html