HDFS安全模式详解

什么是安全模式

安全模式是HDFS所处的一种特殊状态,在这种状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求。在NameNode主节点启动时,HDFS首先进入安全模式,DataNode在启动的时候会向namenode汇报可用的block等状态,当整个系统达到安全标准时,HDFS自动离开安全模式。如果HDFS出于安全模式下,则文件block不能进行任何的副本复制操作,因此达到最小的副本数量要求是基于datanode启动时的状态来判定的,启动时不会再做任何复制(从而达到最小副本数量要求)

下面是namenode的一个日志片段:

安全模式相关的配置

系统什么时候才离开安全模式,需要满足哪些条件?当收到来自datanode的状态报告后,namenode根据配置,确定 1)可用的block占总数的比例、2)可用的数据节点数量符合要求之后,离开安全模式。如果有必要,也可以通过命令强制离开安全模式。与安全模式相关的主要配置在hdfs-site.xml文件中,主要有下面几个属性

  • dfs.namenode.replication.min: 最小的文件block副本数量,默认为1.
  • dfs.namenode.safemode.threshold-pct: 副本数达到最小要求的block占系统总block数的百分比,当实际比例超过该配置后,才能离开安全模式(但是还需要其他条件也满足)。默认为0.999f,也就是说符合最小副本数要求的block占比超过99.9%时,并且其他条件也满足才能离开安全模式。如果为小于等于0,则不会等待任何副本达到要求即可离开。如果大于1,则永远处于安全模式。
  • dfs.namenode.safemode.min.datanodes: 离开安全模式的最小可用(alive)datanode数量要求,默认为0.也就是即使所有datanode都不可用,仍然可以离开安全模式。
  • dfs.namenode.safemode.extension: 当集群可用block比例,可用datanode都达到要求之后,如果在extension配置的时间段之后依然能满足要求,此时集群才离开安全模式。单位为毫秒,默认为1.也就是当满足条件并且能够维持1毫秒之后,离开安全模式。 这个配置主要是对集群的稳定程度做进一步的确认。避免达到要求后马上又不符合安全标准。

总结一下,要离开安全模式,需要满足以下条件:

1)达到副本数量要求的block比例满足要求;

2)可用的datanode节点数满足配置的数量要求;

3) 1、2 两个条件满足后维持的时间达到配置的要求。

我们可以再次从日志中验证这些:

相关的操作命令

Hadoop提供脚本用于对安全模式进行操作,主要命令为:

hadoop dfsadmin -safemode <command>

command的可用取值如下:

command 功能 备注
get 查看当前状态
enter 进入安全模式
leave 强制离开安全模式
wait 一直等待直到安全模式结束

相关源码

安全模式的相关操作封装在SafeMode接口中:

/** 安全模式相关操作 */
@InterfaceAudience.Private
public interface SafeMode {
  /**
   *  检查进入或者退出安全模式的条件是否满足,
   *  如果满足,进入或退出安全模式。
   */
  public void checkSafeMode();

  /** 系统当前是否处于安全模式? */
  public boolean isInSafeMode();

  /**
   * 系统启动时是否自动进入安全模式?
   */
  public boolean isInStartupSafeMode();

  /** Check whether replication queues are being populated. */
  public boolean isPopulatingReplQueues();

  /**
   * 增加达到最小副本数要求的block数
   * @param replication current replication
   */
  public void incrementSafeBlockCount(int replication);

  /** 降低达到最小副本数要求的block数 */
  public void decrementSafeBlockCount(Block b);
}

HDFS的命名系统需要提供安全模式相关的操作,因此实现了改接口,层次结构如下:

Namesystem继承了SafeMode接口,FSNamesystem类实现了Namesystem,间接实现SafeMode定义的操作,也就是我们可以对命名系统进行安全模式相关的操作。

FSNamesystem内部实现了一个内部线程类SafeModeMonitor,周期性地检查是否应该离开安全模式:


  /**
   * 周期性地检测是否可以离开安全模式,逻辑封装在run方法中.
   * This thread starts when the threshold level is reached.
   *
   */
  class SafeModeMonitor implements Runnable {
    /** 两次检测间隔的毫秒数,即1秒 */
    private static final long recheckInterval = 1000;

    /**
     */
    @Override
    public void run() {
      // 系统运行时,循环检测
      while (fsRunning) {
        writeLock();
        try {
          // 没有安全模式相关信息,也就是不在安全模式
          if (safeMode == null) { // Not in safe mode.
            break;//线程退出
          }
          if (safeMode.canLeave()) {
            // Leave safe mode.
            safeMode.leave();
            smmthread = null;
            // 离开安全模式后,线程退出
            break;
          }
        } finally {
          writeUnlock();
        }

        try {
          // 两次检测之间,线程休眠
          Thread.sleep(recheckInterval);
        } catch (InterruptedException ie) {
          // Ignored
        }
      }
      // 当系统不在运行的时候,线程结束退出
      if (!fsRunning) {
        LOG.info("NameNode is being shutdown, exit SafeModeMonitor thread");
      }
    }
  }

这个内部类中出现的safeMode,其类型为SafeModeInfo,用于保存安全模式下的相关信息:

 private volatile SafeModeInfo safeMode;  // safe mode information

注意到这个变量为volatile,也就是说线程对该变量的任何修改完成后,其他线程立刻可以看到变化。OK,那么什么时候会创建这个对象呢,我们用safeMode= new SafeModeInfo搜索源代码,发现2个地方会实例化这个对象:一个实在FSNamesystem的构造函数中,另一处在FSNamesystem类的enterSafeMode方法中。我们先来看构造函数,其方法声明如下:

FSNamesystem(Configuration conf, FSImage fsImage, boolean ignoreRetryCache)
      throws IOException 

这个构造函数使用给定的配置及文件镜像,创建一个文件命名系统。其中有一句如下:

this.safeMode = new SafeModeInfo(conf);

我们去看看SafeModeInfo这个构造函数:

 /**
     * Creates SafeModeInfo when the name node enters
     * automatic safe mode at startup.
     *
     * @param conf configuration
     */
    private SafeModeInfo(Configuration conf) {
      // 这个配置就是我们前面提到的百分比配置
      this.threshold = conf.getFloat(DFS_NAMENODE_SAFEMODE_THRESHOLD_PCT_KEY,
          DFS_NAMENODE_SAFEMODE_THRESHOLD_PCT_DEFAULT);
      if(threshold > 1.0) {
        LOG.warn("The threshold value should‘t be greater than 1, threshold: " + threshold);
      }
    // 这个也是我们前面提到的最小可用datanode数量配置
      this.datanodeThreshold = conf.getInt(
        DFS_NAMENODE_SAFEMODE_MIN_DATANODES_KEY,
        DFS_NAMENODE_SAFEMODE_MIN_DATANODES_DEFAULT);
      this.extension = conf.getInt(DFS_NAMENODE_SAFEMODE_EXTENSION_KEY, 0);
      this.safeReplication = conf.getInt(DFS_NAMENODE_REPLICATION_MIN_KEY,
                                         DFS_NAMENODE_REPLICATION_MIN_DEFAULT);

      LOG.info(DFS_NAMENODE_SAFEMODE_THRESHOLD_PCT_KEY + " = " + threshold);
      LOG.info(DFS_NAMENODE_SAFEMODE_MIN_DATANODES_KEY + " = " + datanodeThreshold);
      LOG.info(DFS_NAMENODE_SAFEMODE_EXTENSION_KEY + "     = " + extension);

      // default to safe mode threshold (i.e., don‘t populate queues before leaving safe mode)
      this.replQueueThreshold =
        conf.getFloat(DFS_NAMENODE_REPL_QUEUE_THRESHOLD_PCT_KEY,
                      (float) threshold);
      this.blockTotal = 0;
      this.blockSafe = 0;
    }

核心逻辑就是获取相关的配置,创建初始的SafeModeInfo。

看看另一个地方:

 /**
   * Enter safe mode. If resourcesLow is false, then we assume it is manual
   * 参数用于区分是因为资源不满足要求还是手动进入安全模式
   * @throws IOException
   */
  void enterSafeMode(boolean resourcesLow) throws IOException {
    writeLock();
    try {
      // Stop the secret manager, since rolling the master key would
      // try to write to the edit log
      stopSecretManager();

      // Ensure that any concurrent operations have been fully synced
      // before entering safe mode. This ensures that the FSImage
      // is entirely stable on disk as soon as we‘re in safe mode.
      boolean isEditlogOpenForWrite = getEditLog().isOpenForWrite();
      // Before Editlog is in OpenForWrite mode, editLogStream will be null. So,
      // logSyncAll call can be called only when Edlitlog is in OpenForWrite mode
      if (isEditlogOpenForWrite) {
        getEditLog().logSyncAll();
      }
      if (!isInSafeMode()) {
        safeMode = new SafeModeInfo(resourcesLow);
        return;
      }
      if (resourcesLow) {
        safeMode.setResourcesLow();
      } else {
        safeMode.setManual();
      }
      if (isEditlogOpenForWrite) {
        getEditLog().logSyncAll();
      }
      NameNode.stateChangeLog.info("STATE* Safe mode is ON"
          + safeMode.getTurnOffTip());
    } finally {
      writeUnlock();
    }
  }

总结一下,SafeModeMonitor作为守护线程,在收到来自datanode的BlockReport状态报告之后,周期性地检测是否达到离开安全模式的条件,如果符合条件,则离开安全模式。

(完)

时间: 2024-08-26 08:22:12

HDFS安全模式详解的相关文章

【转】Hadoop安全模式详解及配置

原文链接 http://www.iteblog.com/archives/977 在<Hadoop 1.x中fsimage和edits合并实现>文章中提到,Hadoop的NameNode在重启的时候,将会进入到安全模式.而在安全模式,HDFS只支持访问元数据的操作才会返回成功,其他的操作诸如创建.删除文件等操作都会导致失败. NameNode在重启的时候,DataNode需要向NameNode发送块的信息,NameNode只有获取到整个文件系统中有99.9%(可以配置的)的块满足最小副本才会自

HDFS节点详解

设计思想 分而治之:将大文件.大批量文件,分布式放在大量服务器上,以便于采取分而治之的方式对海量数据进行预算分析: 在大数据系统中的作用:为各类分布式运算框架(如:MapReduce,Spark等)提供数据存储服务 重要概念:文件切块,副本存放,元数据 HDFS架构 HDFS各节点 NameNode是HDFS的主节点,负责元数据的管理以及客户端对文件的访问.管理数据块的复制,它周期性地从集群中的每个DataNode接收心跳信号和块状态报告(Blockreport) DataNode是HDFS的从

kettle连接hadoop&amp;hdfs图文详解

1 引言: 项目最近要引入大数据技术,使用其处理加工日上网话单数据,需要kettle把源系统的文本数据load到hadoop环境中 2 准备工作: 1 首先 要了解支持hadoop的Kettle版本情况,由于kettle资料网上较少,所以最好去官网找,官网的url: http://wiki.pentaho.com/display/BAD/Configuring+Pentaho+for+your+Hadoop+Distro+and+Version 打开这个url 到页面最下面的底端,如下图: ar

kettle入门(三) 之kettle连接hadoop&amp;hdfs图文详解(转)

1 引言: 项目最近要引入大数据技术,使用其处理加工日上网话单数据,需要kettle把源系统的文本数据load到hadoop环境中 2 准备工作: 1 首先 要了解支持hadoop的Kettle版本情况,由于kettle资料网上较少,所以最好去官网找,官网的url: http://wiki.pentaho.com/display/BAD/Configuring+Pentaho+for+your+Hadoop+Distro+and+Version 打开这个url 到页面最下面的底端,如下图: ar

kettle入门(三) 之kettle连接hadoop&amp;hdfs图文详解

1 引言: 项目最近要引入大数据技术,使用其处理加工日上网话单数据,需要kettle把原始文本数据load到hadoop环境中 2 准备工作: 1 首先 要了解支持hadoop的Kettle版本情况,由于kettle资料网上较少,所以最好去官网找,官网的url: http://wiki.pentaho.com/display/BAD/Configuring+Pentaho+for+your+Hadoop+Distro+and+Version 打开这个url 到打开页面最下面的底端如下图: arc

hdfs功能详解介绍(2)

四.hdfs的安全模式 安全模式是HDFS所处的一种特殊状态,在这种状态下,文件系统只接受读数据请求,而不接受删除.修改等变更请求.在NameNode主节点启动时,HDFS首先进入安全模式,DataNode在启动的时候会向namenode汇报可用的block等状态,当整个系统达到安全标准时,HDFS自动离开安全模式.如果HDFS出于安全模式下,则文件block不能进行任何的副本复制操作,因此达到最小的副本数量要求是基于datanode启动时的状态来判定的,启动时不会再做任何复制(从而达到最小副本

hadoop1中hdfs原理详解

HDFS是Hadoop Distribute File System的简称,也是Hadoop的一个分布四文件系统 一.HDFS的主要设计理念 1.存储超大文件 这里的 “超大文件” 是指几百MB .GB甚至 TB级别的文件. 2.最高效的访问模式是一次写入.多次读取(流式数据访问)  HDFS存储的数据集作为hadoop的分析对象,在数据集生成后,长时间在此数据集上进行各种分析.每次分析都将设计该数据的大部分数据甚至全部数据,因此读取整个数据集的时间延迟比读取第一条记录的时间延迟更重要. 3.运

HDFS入门详解

一. 前提和设计目标 1. 硬件错误是常态,因此需要冗余,这是深入到HDFS骨头里面去了 HDFS可能由成百上千的服务器所构成,每个服务器上存储着文件系统的部分数据.我们面对的现实是构成系统的组件数目是巨大的,而且任一组件都有可能失效,这意味着总是有一部分HDFS的组件是不工作的.因此错误检测和快速.自动的恢复是HDFS最核心的架构目标 2. 流式数据访问 即:数据批量读取而非随机读写(OLTP),Hadoop擅长的是数据分析而不是事物处理 3. 大规模数据集 HDFS上的一个典型文件大小一般都

HDFS概念详解---名称节点与数据节点

HDFS集群有两种节点,以管理者-工作者的模式运行,即一个名称节点(管理者)和多个数据节点(工作者).名称节点管理文件系统的命名空间.它维护着这个文件系统树及这个树内所有的文件和索引目录.这些信息以两种形式将文件永久保存在本地磁盘上:命名空间镜像和编辑日志.名称节点也记录着每个文件的每个块所在的数据节点,但它并不永久保存块的位置,因为这些信息会在系统启动时由数据节点重建. 客户端代表用户通过与名称节点和数据节点交互来访问整个文件系统.客户端提供一个类似POSIX(可移植操作系统界面)的文件系统接