2.4 HDFS 高级特性与优化 本节摘要:前三节揭示的两大痛点——NameNode 单点与三副本存储开销——由本章高级特性回应:NameNode HA 用主备加共享编辑日志消除单点,HDFS 联邦按路径拆分命名空间突破元数据上限,纠删码以约 1.5 倍开销替代 3 倍副本。本节还覆盖小文件治理、数据均衡与缓存等运营级优化。 痛点回顾:单点与开销 2.1 节算过账本内存账,2.2 节看过三副本的带宽账。现在补第三笔账:存储开销。三副本意味着 1 PB 有效数据要占 3 PB 裸容量,加上预留 30% 余量,采购量接近 4.5 PB。冷数据(历史日志、合规归档)同样占三副本,是最大的浪费源。NameNode 单点则是可用性问题:账房先生一停,整个文件系统读写全停,2.
本节摘要:前三节揭示的两大痛点——NameNode 单点与三副本存储开销——由本章高级特性回应:NameNode HA 用主备加共享编辑日志消除单点,HDFS 联邦按路径拆分命名空间突破元数据上限,纠删码以约 1.5 倍开销替代 3 倍副本。本节还覆盖小文件治理、数据均衡与缓存等运营级优化。
2.1 节算过账本内存账,2.2 节看过三副本的带宽账。现在补第三笔账:存储开销。三副本意味着 1 PB 有效数据要占 3 PB 裸容量,加上预留 30% 余量,采购量接近 4.5 PB。冷数据(历史日志、合规归档)同样占三副本,是最大的浪费源。NameNode 单点则是可用性问题:账房先生一停,整个文件系统读写全停,2.1 节也提过 SecondaryNameNode 并非热备。两个痛点,四个答案。
HA 的思路朴素:部署两台 NameNode,一主(Active)一备(Standby),任何时刻只有主对外服务。难点在于备机怎么保持账本最新——答案是一份共享的 EditLog。现代部署用三个 JournalNode 组成法定人数(Quorum)集群:主 NameNode 的每条元数据变更先写入多数 JournalNode 才算成功,备机持续从 JournalNode 拉取并回放进自己的内存账本。这样备机的内存状态始终只落后主数毫秒。
故障切换由独立的 ZooKeeper 与每个 NameNode 上的 ZKFC(故障转移控制器)协作完成:ZKfc 持有 ZooKeeper 会话,会话断开即失去锁,另一侧立刻接管并把自己升为主。人工切换用一条命令:
hdfs haadmin -failover nn1 nn2 # 把主从nn1切到nn2 # 典型输出:Failover from nn1 to nn2 successful

切换的最后一环是防脑裂(Split-brain):原主可能只是假死(GC 长暂停),恢复后仍认为自己为主。HDFS 用"旧主必须先放弃 ZooKeeper 锁、并可配置对原主隔离 SSH 杀进程"兜底,确保任何时刻至多一个 Active。
HA 解决可用性,联邦解决容量。思路:多个 NameNode 各管一部分命名空间(如 nn1 管 /data、nn2 管 /warehouse、nn3 管 /user),共享同一批 DataNode。客户端通过挂载表把路径路由到对应 NameNode。联邦后单本账本的内存压力分散,集群可容纳的文件数成倍增长。代价是运维复杂度:每个 NameNode 一套 HA、跨命名空间操作不支持原子性。实践中联邦多用于超大规模(数十亿文件)场景,中小集群通常用治理小文件来延缓账本膨胀。
纠删码(Erasure Coding,EC)用编码冗余替代全量副本。HDFS 默认采用 RS(6,3) 纠删码:数据切成 6 个单元,计算 3 个校验单元,共 9 个单元分布在 9 个节点;任意丢失 3 个单元都可重建。存储开销 9/6 = 1.5 倍,对比三副本的 3 倍,冷数据存储直接省一半。
代价有两点。其一,写放大与计算开销:写入要做编码计算,恢复要读剩余单元重算。其二,读取放大:三副本下任何一个副本可独立服务全量数据;EC 下读单个条带单元若损坏需跨 6 节点重组。所以 EC 适合"写少读少、容量敏感"的冷数据,热数据仍用三副本。策略按目录指定:
hdfs ec -setPolicy -policy RS-6-3-1024k -path /archive/2024 hdfs ec -getPolicy /archive/2024 # RS-6-3-1024k:6数据单元+3校验单元 单元1MB
一个规划细节:EC 条带要求至少 9 个 DataNode(HDFS 3.x 起小集群可用 RS(3,2),5 节点即可),上线前要核对集群规模。
2.1 节算过账本账:每文件约 150 字节元数据,1 亿小文件就是几十 GB 内存。治理手段按层次:
| 手段 | 做法 | 适用 |
|---|---|---|
| 序列文件打包 | 大量小图/文档打包为少量大文件 | 建模前离线处理 |
| HAR 归档 | 原地打包成 .har,透明访问 | 已有存量小文件 |
| 分区合并 | 数仓按天/按小时合并分区文件 | Hive 数仓(第5章) |
| 联邦 | 多本账本分摊 | 超大规模 |
运营侧配合两条:hdfs dfsadmin -metasave meta.txt 导出账本统计分布;上线摄入管道时强制"单文件不小于 128MB"的规范,从源头控制。
数据均衡。长期写入删除后,各 DataNode 磁盘利用率会失衡(比如新扩容节点空载、老节点 95%)。Balancer 按阈值搬块:
hdfs balancer -threshold 10 # 各节点利用率与均值差不超过10%即达标 # 典型输出: # Time Stamp Iteration# Bytes Already Moved ... 12,884,901,888 # The cluster is balanced. Exiting...
搬块本身消耗磁盘 IO 与网络,生产上应限速(-bandwidth 参数,单位 MB/s)并避开业务高峰。
集中式缓存。NameNode 可把指定文件或目录锁定在 DataNode 的堆外内存缓存中,重复热读(如维表、字典文件)免去磁盘路径。配合第 3 章 Map 任务的内存输入,对 join 小维表场景提升明显。
存储层的旅程到此完整。下一章进入计算:MapReduce 如何让躺在块里的数据动起来。