HDFS NameNode启动时的详细流程是怎样的?
HDFS NameNode 的启动流程是 Hadoop 体系中最核心的机制之一。为了保证数据的强一致性和高可用性,启动过程设计得非常严密。
我们可以将 NameNode 的启动全流程划分为以下 五个核心阶段:
第一阶段:初始化与配置加载 (Initialization)
- 加载配置文件:NameNode 进程启动后,首先读取
core-site.xml和hdfs-site.xml中的配置信息(如目录路径、RPC 端口、HTTP 端口、HA 配置等)。 - 环境校验:检查配置的本地数据目录(
dfs.namenode.name.dir)是否存在且具有读写权限。如果是高可用(HA)模式,还会初始化与 JournalNode 集群的连接配置。 - 实例化核心组件:创建
FSNamesystem(管理文件系统元数据)、BlockManager(管理数据块与 DataNode 的映射关系)等核心对象。
第二阶段:元数据加载 (Metadata Loading) —— 【最核心步骤】
NameNode 并不把“文件存在哪个 DataNode 上”的信息持久化到磁盘,磁盘上只存文件目录树(Namespace)。
- 读取 FsImage(镜像文件):
- NameNode 找到本地磁盘上最新的
fsimage文件(例如fsimage_0000000000000000100)。 - 将该文件加载到内存中,构建出文件系统的目录树(Namespace)。此时内存中的状态是系统在某一个历史时间点的快照。
- NameNode 找到本地磁盘上最新的
- 回放 EditLog(编辑日志):
- 仅有 FsImage 是不够的,NameNode 会查找生成该 FsImage 之后的所有
edits日志文件(例如edits_0000000000000000101-0000000000000000200)。 - 如果是 HA 架构,NameNode 会从 JournalNode 集群拉取尚未合并的 edits 日志。
- 将这些日志在内存中逐条执行(回放),将内存中的目录树更新到系统关闭前最新的状态。
- 仅有 FsImage 是不够的,NameNode 会查找生成该 FsImage 之后的所有
- 保存新的 Checkpoint(可选操作):
- 元数据合并完成后,NameNode 会将内存中最新的目录树生成一个新的
fsimage文件保存到本地磁盘,并生成一个新的、空的edits日志文件,更新 Transaction ID(事务ID)。
- 元数据合并完成后,NameNode 会将内存中最新的目录树生成一个新的
第三阶段:启动网络服务 (Service Startup)
元数据在内存中构建完毕后,NameNode 准备好对外通信:
- 启动 RPC Server:开启 RPC 服务(默认端口 8020 或 9000),开始接收 DataNode 的注册和心跳,以及客户端的请求。
- 启动 HTTP Server:开启 Web UI 服务(Hadoop 2.x 默认 50070 端口,Hadoop 3.x 默认 9870 端口),提供可视化管理界面。
第四阶段:进入安全模式与块汇报 (Safe Mode & Block Report)
此时的 NameNode 知道系统中有哪些文件,以及每个文件由哪些 Block 组成,但它 不知道这些 Block 实际存储在哪些 DataNode 上。因此必须进入安全模式。
- 进入安全模式 (Safe Mode):
- 在此模式下,文件系统是只读的。客户端无法进行上传、删除、修改副本数等操作,只能浏览目录或下载文件。
- DataNode 注册与心跳:
- 各个 DataNode 启动,通过 RPC 向 NameNode 注册自己,并开始周期性发送心跳(默认3秒一次)。
- 全量块汇报 (Block Report):
- DataNode 扫描本地磁盘,将自己拥有的所有 Block 信息打包,发送给 NameNode。
- NameNode 接收到汇报后,在内存的
BlockManager中动态构建 Block -> DataNode 列表 的映射关系(BlockMap)。
- 校验与退出安全模式:
- NameNode 会不断统计已汇报的、满足最小副本数(
dfs.namenode.replication.min,默认是 1)的 Block 数量。 - 当 安全块比例 达到阈值(
dfs.namenode.safemode.threshold-pct,默认 0.999,即 99.9% 的数据块都已经找到了至少一个副本)时。 - 达到阈值后,NameNode 会再等待一段缓冲时间(
dfs.namenode.safemode.extension,默认 30 秒),以期收到更多的 DataNode 汇报。 - 缓冲时间结束后,自动退出安全模式。
- NameNode 会不断统计已汇报的、满足最小副本数(
- 处理异常数据块:退出安全模式后,NameNode 会立即检查哪些块副本不足(触发复制)或哪些块副本过多(触发删除)。
第五阶段:HA 状态选举 (仅限 HA 模式)
如果在集群中配置了高可用(HA):
- NameNode 启动后初始状态均为 Standby(备用状态)。
- ZKFC(ZooKeeper Failover Controller)进程会参与 ZooKeeper 的排他锁选举。
- 选举成功的 NameNode 被切换为 Active(活跃状态),开始对外提供写入服务,并将后续的操作日志写入 JournalNode。
- 选举失败的 NameNode 保持 Standby 状态,持续从 JournalNode 读取 EditLog,充当热备和 Checkpoint(替代 SecondaryNameNode 功能)的角色。
总结:一图胜千言(流程精简版)
加载配置 ➡️ 读 FsImage 到内存 ➡️ 回放 EditLog 更新内存 ➡️ 启动 RPC/HTTP 服务 ➡️ 进入安全模式 ➡️ 接收 DataNode 块汇报 ➡️ 构建 BlockMap ➡️ 达到 99.9% 阈值并等待 30 秒 ➡️ 退出安全模式 ➡️ 正常对外服务 (或进行 HA 选举)
面试常考点提示:
- 为什么进入安全模式? 因为 NameNode 磁盘上不存 Block 位置信息,需要等 DataNode 汇报上来,期间为防数据误判丢失,必须只读。
- Namespace 和 BlockMap 的区别? Namespace 是文件目录树(持久化在 FsImage),BlockMap 是块和节点映射关系(纯内存,每次启动靠 DataNode 汇报动态生成)。