hdfs的安全模式

这是我的第106篇原创文章

一、安全模式简介

在hdfs中,namenode为保证数据一致性、可靠性,而进入的一种状态,称之为安全模式(SafeMode)。在安全模式下,客户端只能进行数据的读取操作,而不能进行创建、删除、重命名文件目录等操作,即在安全模式下,不能对hdfs文件系统做任何修改。

通常情况下,namenode在启动通过fsimage与editlog完成文件系统的加载之后,就会自动进入安全模式。此后等待各个datanode的注册,以及通过心跳进行的全量块汇报。

当在线(完成注册)的Datanode达到一定的个数,同时汇报的块个数达到一定的比例后,namenode自动离开安全模式。

二、运行过程中的安全模式检测

从namenode启动进入安全模式,到满足条件离开安全模式。在这之后,如果有Datanode下线,或者Datanode的磁盘损坏,导致在线的Datanode没有满足指定个数,或者汇报的block数量无法达到指定的比例时,是否还会重新再进入安全模式呢?

答案是否定的,Datanode在线数与block汇报率这两个指标仅在namenode启动时进行强检验,在离开安全模式之后,即便条件不满足也不会再次进入安全模式。

但是,namenode在启动后,内部会启动一个资源监测线程,定时检测资源是否满足指定条件。这些资源指的就是配置的用于存储editlog、fsiamge的存储卷目录;指定条件则是存储卷目录的剩余可用空间大于配置项指定的值(默认100MB),当有资源不满足条件时,即存储卷目录可用剩余空间小于指定大小时,则主动进入安全模式。

注意:资源检测线程发现存储空间不够时会触发进入安全模式,但代码中还存在BUG:即存储空间进行了释放达到可用的条件时,不会自动退出安全模式,这个问题在最新release版本中才修复。

资源检测与问题修复代码如下所示:

ee51607d9e2af0305791e17cdf45eced.jpeg

三、命令手动进入退出安全模式&特殊场景

除了这两种方式可以进入/退出安全模式之外, 我们还可以通过命令的方式主动设置进入安全模式或离开安全模式。

# 获取当前安全模式的状态
hdfs dfsadmin -safemode get
# 进入安全模式
hdfs dfsadmin -safemode enter
# 离开安全模式
hdfs dfsadmin -safemode leave
# 强制退出安全模式
hdfs dfsadmin -safemode forceExit

在上面提到的两种场景中,通过命令可以手动退出安全模式,那么在什么场景下,即便调用"-safemode leave"还不能退出安全模式,必须调用强制退出安全模式才能真正退出安全模式呢?

NN在处理DN首次全量块汇报时,如果DN汇报的块在NN中找不到对应的元数据记录信息,同时上报的这个块的时间戳比NN内部的时间戳还要大,在NN内部会认为这是一个"未来时间"写入的块,单独进行记录。

void processFirstBlockReport(
    final DatanodeStorageInfo storageInfo, 
    final BlockListAsLongs report) 
    throws IOException {
    ...
    for(BlockReportReplica iblk : report) {
        ...
        BlockInfo storedBlock = getStoredBlock(iblk);
        if(storedBlock == null) {
            bmSafeMode.checkBlocksWithFutureGS(iblk);
            continue;
        }
        ...
    }
}

void checkBlocksWithFutureGS(BlockReportReplica brr) {
    assert namesystem.hasWriteLock();
    if(status == BMSafeModeStatus.OFF) {
        return;
    }
    if (!blockManager.getShouldPostponeBlocksFromFuture() && 
        !inRollBack && 
        blockManager.isGenStampInFuture(brr)) {
        if(blockManager.getBlockIdManager().isStripedBlock(brr)) {
            bytesInFutureECBlockGroups.add(brr.getBytesOnDisk());
        } else {
            bytesInFutureBlocks.add(brr.getBytesOnDisk());
        }
    }
}

之后,即便DN在线个数与块汇报率满足条件,也不会退出安全模式,此时,只能通过命令人为强制退出安全模式。相当于需要人工确认这些块是没有问题的,而不是可能的元数据丢失。

boolean leaveSafeMode(boolean force) {
    final long bytesInFuture = getBytesInFuture();
    if(bytesInFuture > 0) {
        if(force) {
            LOG.warn("Leaving safe mode due to forceExit. This will cause a data " + "loss of {} byte(s).", bytesInFuture);
            bytesInFutureBlocks.reset();
            bytesInFutureECBlockGroups.reset();
        } else {
            ...
            return false;
        }
    } else if(force) {
        LOG.warn(...);
    }
}

这种情况,多发生在升级回滚的场景。比如,先对NN的元数据进行了备份,然后进行升级,升级过程中写入了少量文件,再使用备份的元数据进行回滚,就会出现DN中新写入的块的时间戳要大于NN中记录的时间戳,同时由于是新写入的文件,在老的备份的元数据中不存在对应的信息,在DN注册进行全量块汇报时自然就出现了这种情况了。

四、相关配置

安全模式相关的配置包括:

配置项默认值说明
dfs.internal.nameservices5000(单位:毫秒)ANN启动检测资源是否满足条件的时间间隔
dfs.namenode.safemode.min.datanodes0启动后离开安全模式的最小存活datanode个数
dfs.namenode.safemode.threshold-pct0.999启动后离开安全模式的block块的汇报百分比
dfs.namenode.resource.check.interval5000(单位:毫秒)资源检测的时间间隔
dfs.namenode.resource.du.reserved100MBnamenode存储卷目录预留大小

总结

本文介绍了hdfs安全模式的相关知识,包括启动进入安全模式、离开安全模式的条件、资源监测引起的安全模式进入与离开、以及运维操作命令手动进入安全模式与离开。

好了,这就是本文的全部内容,如果觉得本文对您有帮助,请点赞+转发,如果觉得有不正确的地方,欢迎留言交流~

参考:

[1] https://issues.apache.org/jira/browse/HDFS-17231

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值