HDFS 高级特性
本章将深入讲解 HDFS 的高级特性,包括副本机制、机架感知、纠删码、高可用配置等。
副本放置策略
机架感知
HDFS 的副本放置策略依赖于机架感知(Rack Awareness),即知道每个 DataNode 所在的机架位置。
为什么需要机架感知?
数据中心通常将服务器部署在多个机架上,每个机架有自己的网络交换机:
- 机架内带宽高:同一机架内节点间通信速度快
- 机架间带宽有限:跨机架通信需要经过核心交换机
- 机架故障风险:机架电源、交换机故障会影响整个机架
机架感知让 HDFS 能够:
- 优化副本放置,提高数据可靠性
- 优先读取本地或同机架数据,提高读取性能
- 减少跨机架网络传输
配置机架感知
HDFS 通过脚本实现机架感知,需要配置拓扑脚本:
1. 编写拓扑脚本
#!/usr/bin/env python3
import sys
RACK_MAP = {
"192.168.1.101": "/rack1",
"192.168.1.102": "/rack1",
"192.168.1.103": "/rack2",
"192.168.1.104": "/rack2",
"192.168.1.105": "/rack3",
"192.168.1.106": "/rack3",
}
for ip in sys.argv[1:]:
print(RACK_MAP.get(ip, "/default-rack"))
2. 配置 core-site.xml
<property>
<name>net.topology.script.file.name</name>
<value>/opt/hadoop/etc/hadoop/rack-topology.sh</value>
</property>
<property>
<name>net.topology.script.number.args</name>
<value>100</value>
</property>
副本放置策略详解
默认策略(3 副本)
放置规则:
| 副本 | 位置选择 | 原因 |
|---|---|---|
| 第1个 | 客户端所在节点(如果在集群内),否则随机 | 减少网络传输 |
| 第2个 | 不同机架的随机节点 | 机架级容错 |
| 第3个 | 第2个副本同机架的不同节点 | 平衡可靠性和性能 |
多副本策略(超过3个)
当副本数大于3时:
- 第1个副本:客户端所在节点或随机
- 第2个副本:不同机架
- 第3个副本:第2个副本同机架
- 其余副本:随机选择,避免过多副本在同一机架
副本管理
副本监控
# 查看文件副本信息
hdfs fsck /user/hadoop/file.txt -files -blocks -racks
# 查看副本不足的块
hdfs fsck / -list-corruptfileblocks
# 查看集群副本统计
hdfs dfsadmin -report
副本调整
# 修改文件副本数
hdfs dfs -setrep 5 /user/hadoop/file.txt
# 递归修改目录副本数
hdfs dfs -setrep -R 3 /user/hadoop/
# 查看副本设置
hdfs fsck /user/hadoop/file.txt -files
副本迁移
当需要下线某个 DataNode 时,需要迁移其上的数据:
# 1. 将节点加入排除列表
echo "datanode-to-decommission" >> $HADOOP_HOME/etc/hadoop/dfs.exclude
# 2. 刷新节点配置
hdfs dfsadmin -refreshNodes
# 3. 监控迁移进度
hdfs dfsadmin -report
# 4. 迁移完成后,从包含列表移除节点
纠删码(Erasure Coding)
什么是纠删码?
纠删码是 Hadoop 3.x 引入的新特性,相比多副本机制可以节省约50%的存储空间。
基本原理:
将数据分成 k 个数据块,计算生成 m 个校验块,共 k+m 个块。可以容忍任意 m 个块丢失。
纠删码 vs 多副本
| 特性 | 多副本(3副本) | 纠删码(RS-6-3) |
|---|---|---|
| 存储开销 | 200% 额外空间 | 50% 额外空间 |
| 容错能力 | 2 个节点故障 | 3 个节点故障 |
| 读取性能 | 高(就近读取) | 一般(可能需要解码) |
| 写入性能 | 高 | 较低(需要计算校验块) |
| 适用场景 | 热数据、小文件 | 冷数据、大文件 |
纠删码策略
Hadoop 3.x 支持多种纠删码策略:
| 策略 | 数据块:校验块 | 存储开销 | 容错能力 |
|---|---|---|---|
| RS-3-2-1024k | 3:2 | 66.7% | 2 块 |
| RS-6-3-1024k | 6:3 | 50% | 3 块 |
| RS-10-4-1024k | 10:4 | 40% | 4 块 |
| XOR-2-1-1024k | 2:1 | 50% | 1 块 |
启用纠删码
1. 检查集群是否支持纠删码
hdfs ec -listPolicies
2. 启用纠删码策略
# 启用 RS-6-3-1024k 策略
hdfs ec -enablePolicy -policy RS-6-3-1024k
3. 为目录设置纠删码
# 创建目录
hdfs dfs -mkdir /ec-data
# 设置纠删码策略
hdfs ec -setPolicy -path /ec-data -policy RS-6-3-1024k
# 验证设置
hdfs ec -getPolicy -path /ec-data
4. 写入数据
# 上传文件(会自动使用纠删码存储)
hdfs dfs -put largefile.txt /ec-data/
纠删码配置
<!-- 启用纠删码 -->
<property>
<name>dfs.namenode.ec.enabled</name>
<value>true</value>
</property>
<!-- 纠删码策略 -->
<property>
<name>dfs.namenode.ec.system.default.policy</name>
<value>RS-6-3-1024k</value>
</property>
<!-- 编码器实现 -->
<property>
<name>io.native.lib.available</name>
<value>true</value>
</property>
HDFS 高可用(HA)
高可用架构
HDFS 高可用通过 Active/Standby NameNode 实现,避免单点故障:
核心组件
JournalNode(JN)
JournalNode 集群用于存储 EditLog,实现 Active 和 Standby 之间的数据同步:
- 至少需要 3 个 JournalNode
- Active NameNode 将 EditLog 写入 JournalNode
- Standby NameNode 从 JournalNode 读取 EditLog 并应用到内存
ZooKeeper(ZK)
ZooKeeper 用于:
- 自动故障检测
- 主备选举
- 存储 Active NameNode 锁
ZKFC(ZooKeeper Failover Controller)
ZKFC 运行在每个 NameNode 上:
- 监控 NameNode 健康状态
- 向 ZooKeeper 注册
- 触发故障转移
高可用配置
core-site.xml
<!-- 集群名称 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<!-- ZooKeeper 地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>zk1:2181,zk2:2181,zk3:2181</value>
</property>
hdfs-site.xml
<!-- 集群配置 -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<!-- NameNode 标识 -->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<!-- NameNode RPC 地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>node1:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>node2:8020</value>
</property>
<!-- NameNode HTTP 地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>node1:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>node2:9870</value>
</property>
<!-- JournalNode 地址 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://jn1:8485;jn2:8485;jn3:8485/mycluster</value>
</property>
<!-- JournalNode 数据目录 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/opt/hadoop/data/journalnode</value>
</property>
<!-- 故障转移代理 -->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 隔离机制 -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<!-- 自动故障转移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
高可用集群启动
# 1. 启动 ZooKeeper(在 ZooKeeper 节点执行)
zkServer.sh start
# 2. 启动 JournalNode(在 JournalNode 节点执行)
hdfs --daemon start journalnode
# 3. 格式化 NameNode(在第一个 NameNode 执行)
hdfs namenode -format
# 4. 启动第一个 NameNode
hdfs --daemon start namenode
# 5. 同步第二个 NameNode(在第二个 NameNode 执行)
hdfs namenode -bootstrapStandby
# 6. 启动第二个 NameNode
hdfs --daemon start namenode
# 7. 初始化 ZooKeeper 故障转移
hdfs zkfc -formatZK
# 8. 启动 ZKFC(在 NameNode 节点执行)
hdfs --daemon start zkfc
# 9. 启动 DataNode
hdfs --daemon start datanode
手动故障转移
# 查看当前状态
hdfs haadmin -getAllServiceState
# 手动切换 Active
hdfs haadmin -transitionToActive nn1
# 手动切换到 Standby
hdfs haadmin -transitionToStandby nn2
# 强制切换(不推荐)
hdfs haadmin -transitionToActive --forcemanual nn1
HDFS 联邦(Federation)
什么是 HDFS 联邦?
HDFS 联邦允许集群中有多个 NameNode,每个 NameNode 管理独立的命名空间:
联邦的优势
- 扩展性:突破单个 NameNode 内存限制
- 隔离性:不同业务使用独立命名空间
- 性能:分散元数据访问压力
联邦配置
<!-- core-site.xml -->
<property>
<name>fs.defaultFS</name>
<value>viewfs://mycluster</value>
</property>
<!-- 挂载表配置 -->
<property>
<name>fs.viewfs.mounttable.mycluster.link./data1</name>
<value>hdfs://nn1:8020/data1</value>
</property>
<property>
<name>fs.viewfs.mounttable.mycluster.link./data2</name>
<value>hdfs://nn2:8020/data2</value>
</property>
异构存储
存储类型
Hadoop 3.x 支持异构存储,可以根据数据热度选择不同存储介质:
| 存储类型 | 说明 | 适用场景 |
|---|---|---|
| RAM_DISK | 内存 | 极热数据 |
| SSD | 固态硬盘 | 热数据 |
| DISK | 机械硬盘 | 温数据 |
| ARCHIVE | 归档存储 | 冷数据 |
存储策略
| 策略 | 副本放置 | 说明 |
|---|---|---|
| Hot | DISK:3 | 默认策略 |
| Warm | DISK:1, ARCHIVE:2 | 温数据 |
| Cold | ARCHIVE:3 | 冷数据 |
| All_SSD | SSD:3 | 全 SSD |
| One_SSD | SSD:1, DISK:2 | 混合存储 |
| Lazy_Persist | RAM_DISK:1, DISK:1 | 内存优先 |
配置异构存储
1. 配置 DataNode 存储目录
<property>
<name>dfs.datanode.data.dir</name>
<value>[SSD]file:///ssd0,[DISK]file:///disk0,[ARCHIVE]file:///archive0</value>
</property>
2. 设置目录存储策略
# 设置目录为热数据策略
hdfs storagepolicies -setStoragePolicy -path /hot-data -policy Hot
# 设置目录为冷数据策略
hdfs storagepolicies -setStoragePolicy -path /cold-data -policy Cold
# 查看存储策略
hdfs storagepolicies -getStoragePolicy -path /hot-data
小结
本章介绍了 HDFS 的高级特性:
-
副本放置策略:机架感知优化副本分布,提高可靠性和性能。
-
纠删码:相比多副本节省存储空间,适合冷数据存储。
-
高可用:Active/Standby NameNode 实现故障自动转移。
-
联邦:多 NameNode 扩展集群规模。
-
异构存储:根据数据热度选择不同存储介质。
这些高级特性让 HDFS 能够更好地适应不同的业务场景,是构建企业级大数据平台的重要基础。