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之间流转的。到时候我会分享一个我在调优过程中踩过的坑——保证让你印象深刻。