跳到主要内容

HDFS 高级特性

本章将深入讲解 HDFS 的高级特性,包括副本机制、机架感知、纠删码、高可用配置等。

副本放置策略

机架感知

HDFS 的副本放置策略依赖于机架感知(Rack Awareness),即知道每个 DataNode 所在的机架位置。

为什么需要机架感知?

数据中心通常将服务器部署在多个机架上,每个机架有自己的网络交换机:

  • 机架内带宽高:同一机架内节点间通信速度快
  • 机架间带宽有限:跨机架通信需要经过核心交换机
  • 机架故障风险:机架电源、交换机故障会影响整个机架

机架感知让 HDFS 能够:

  1. 优化副本放置,提高数据可靠性
  2. 优先读取本地或同机架数据,提高读取性能
  3. 减少跨机架网络传输

配置机架感知

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-1024k3:266.7%2 块
RS-6-3-1024k6:350%3 块
RS-10-4-1024k10:440%4 块
XOR-2-1-1024k2:150%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 管理独立的命名空间:

联邦的优势

  1. 扩展性:突破单个 NameNode 内存限制
  2. 隔离性:不同业务使用独立命名空间
  3. 性能:分散元数据访问压力

联邦配置

<!-- 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归档存储冷数据

存储策略

策略副本放置说明
HotDISK:3默认策略
WarmDISK:1, ARCHIVE:2温数据
ColdARCHIVE:3冷数据
All_SSDSSD:3全 SSD
One_SSDSSD:1, DISK:2混合存储
Lazy_PersistRAM_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 的高级特性:

  1. 副本放置策略:机架感知优化副本分布,提高可靠性和性能。

  2. 纠删码:相比多副本节省存储空间,适合冷数据存储。

  3. 高可用:Active/Standby NameNode 实现故障自动转移。

  4. 联邦:多 NameNode 扩展集群规模。

  5. 异构存储:根据数据热度选择不同存储介质。

这些高级特性让 HDFS 能够更好地适应不同的业务场景,是构建企业级大数据平台的重要基础。