2、HDFS核心架构:NameNode与DataNode的角色、Secondary NameNode的职责、HDFS 2.x与3.x架构演进

2.1 先聊聊HDFS的整体设计思路

HDFS,说白了就是一个「主从架构」的分布式文件系统。我刚开始接触Hadoop时,觉得这东西挺玄乎——不就是存文件吗?搞这么复杂干嘛?后来在项目中真正处理PB级数据时,才明白它的设计哲学。

HDFS的核心思想很简单:把大文件切成小块,分散存储在多台机器上。但难点在于——谁来管这些块?谁负责存?挂了怎么办?

这就引出了我们今天的主角:NameNode(老大)和DataNode(小弟)。

2.2 NameNode:集群的「大脑」

NameNode是HDFS的元数据服务器。它不存实际数据,只存「数据在哪」的信息。

具体来说,NameNode管理两样东西:

  • 文件系统的目录树——哪个文件在哪个目录,权限是什么
  • 文件到数据块的映射关系——一个文件被切成了几个块,每个块存在哪些DataNode上

我习惯把NameNode比作「图书馆的索引卡片柜」。你找书(文件)时,先查卡片(元数据),知道书在哪个书架(DataNode)上,然后直接去拿。卡片柜本身不存书,但没它你就找不到书。

关键点:NameNode是整个HDFS的单点。它挂了,整个集群就不可用了。这不是危言耸听——我在2018年就遇到过生产环境NameNode宕机,导致整个离线数仓停了6小时。

NameNode在内存中维护着完整的元数据。为了持久化,它会把元数据写入两个文件:

  • FsImage:文件系统元数据的完整快照
  • EditLog:自上次快照以来的所有修改操作日志

启动时,NameNode会加载FsImage,然后重放EditLog,重建内存中的元数据状态。

2.3 DataNode:真正的「搬砖工」

DataNode就简单多了——它只管存数据块,并定期向NameNode汇报。

每个DataNode负责:

  • 存储实际的数据块(默认128MB一块)
  • 处理客户端的读写请求
  • 定期向NameNode发送心跳和块报告
  • 执行数据块的复制、删除、恢复等操作

你想想看,一个HDFS集群可能有几百上千个DataNode。NameNode怎么知道它们还活着?靠心跳。DataNode每3秒发一次心跳,如果NameNode超过10分钟没收到某个DataNode的心跳,就会把它标记为「死亡」,然后启动数据块复制流程。

避坑指南:我曾经遇到过DataNode磁盘写满导致心跳超时的情况。NameNode判定节点死亡后,开始大量复制数据块,结果其他节点也被撑爆了。后来我养成了习惯——给DataNode的磁盘使用率设置告警阈值,超过85%就提前处理。

2.4 Secondary NameNode:不是备胎,是「秘书」

很多人刚学HDFS时,以为Secondary NameNode是NameNode的热备。错!大错特错!

Secondary NameNode的职责只有一个:帮助NameNode合并FsImage和EditLog

为什么需要合并?因为EditLog会不断增长。如果NameNode重启,需要重放所有EditLog,时间会越来越长。Secondary NameNode定期(默认1小时)从NameNode拉取FsImage和EditLog,在内存中合并,生成新的FsImage,再传回NameNode。

说白了,它就是个「保洁阿姨」——定期帮你整理文件,让你下次启动时不用翻遍所有历史记录。

注意:Secondary NameNode不是高可用方案。如果NameNode挂了,Secondary NameNode不能自动接管。它只是减轻了NameNode的合并负担。真正的HA方案,我们后面会讲。

2.5 HDFS 2.x架构演进:从单点到高可用

HDFS 1.x最大的痛点就是NameNode单点故障。我记得有个同事说过:「每次NameNode重启,全组人都得盯着屏幕祈祷。」

HDFS 2.x引入了NameNode高可用(HA)架构,核心变化:

  • 两个NameNode:Active和Standby
  • 共享存储(JournalNode集群)保存EditLog
  • Active写入EditLog,Standby实时读取并重放
  • ZKFC(ZooKeeper Failover Controller)监控健康状态,自动切换

这样一来,Active挂了,Standby秒级接管。用户几乎无感知。

另一个重要改进是HDFS Federation(联邦)。说白了,就是多个NameNode管理不同的命名空间,每个NameNode负责一部分目录。这样解决了单个NameNode内存瓶颈的问题。

特性 HDFS 1.x HDFS 2.x
NameNode高可用 不支持 支持(Active/Standby)
命名空间扩展 单NameNode 支持Federation
EditLog存储 本地磁盘 JournalNode集群
故障切换 手动恢复 自动切换(ZKFC)

2.6 HDFS 3.x架构演进:更轻、更快、更稳

HDFS 3.x在2.x的基础上做了不少优化。我个人最关注的有三点:

第一,纠删码(Erasure Coding)。以前数据冗余靠副本(默认3副本),存储开销是300%。纠删码可以把开销降到150%左右,同时保证同样的容错能力。说白了,就是用计算换存储。我在冷数据存储场景中试过,存储成本直接降了40%。

第二,多个Standby NameNode。2.x只能有一个Standby,3.x支持多个。这样在超大集群中,故障切换更灵活。

第三,内建负载均衡和磁盘均衡器。以前DataNode磁盘使用不均,得手动跑balancer。3.x的Intra-DataNode balancer可以自动均衡同一节点内不同磁盘的使用率。

升级建议:如果你还在用HDFS 2.x,我建议至少评估一下纠删码特性。对于存储成本敏感的场景,这绝对是值得的。但要注意——纠删码对CPU有额外消耗,写入性能会略有下降。

2.7 架构演进总结

从1.x到3.x,HDFS的演进脉络很清晰:

  • 1.x:解决了「能不能用」的问题
  • 2.x:解决了「稳不稳定」的问题(HA + Federation)
  • 3.x:解决了「省不省钱」的问题(纠删码 + 性能优化)

嗯,这里要注意——架构演进不是一蹴而就的。我在实际项目中见过不少团队,明明业务量不大,却非要上Federation,结果运维复杂度翻倍。选型时一定要结合自己的场景,别为了用新技术而用新技术。

下一章,我们会深入HDFS的读写流程,看看数据到底是怎么在NameNode和DataNode之间流转的。到时候我会分享一个我在调优过程中踩过的坑——保证让你印象深刻。