HDFS 数据迁移
1. 概述
本文介绍如何将源集群中的 HDFS 数据迁移到目标集群的 HDFS,聚焦 HDFS 数据本身的迁移。
HDFS 数据迁移推荐使用 Hadoop DistCp。DistCp 基于 MapReduce 并行复制数据,适合大目录、大文件量、大数据量的跨集群迁移。
2. 迁移方案
当目标集群能够访问源集群 NameNode 和 DataNode 时,推荐直接使用 DistCp 从源 HDFS 复制到目标 HDFS。
适合场景:
- 新旧集群网络互通。
- 源集群 HDFS 服务可被目标集群访问。
- 迁移窗口内网络带宽稳定。
3. 迁移前准备
迁移前需要确认以下信息。
3.1 集群和网络
| 检查项 | 说明 |
|---|---|
| 源集群 HDFS 地址 | 例如 hdfs://source-nn:8020 或源集群 nameservice |
| 目标集群 HDFS 地址 | 通常在目标集群上执行迁移命令,可直接使用本地 HDFS 路径,例如 /data |
| 网络连通性 | 目标集群需要能够访问源集群 NameNode 和 DataNode |
| 带宽 | 评估迁移数据量、可用带宽和迁移窗口 |
| 防火墙/安全组 | 确认 HDFS RPC、DataNode 数据传输端口可访问 |
如果源集群为 HDFS HA 模式,建议使用源集群的 nameservice 地址;如果无法使用 nameservice,需要确认使用的是当前 Active NameNode 地址。
3.2 权限
| 检查项 | 说明 |
|---|---|
| 源目录读权限 | 执行迁移的用户需要对源 HDFS 目录有读权限 |
| 目标父目录写权限 | 执行迁移的用户需要能在目标 HDFS 父目录下创建或写入目标目录 |
| 用户和组 | 如果需要保留属主、属组,目标集群应存在对应用户和组 |
3.3 迁移目录清单
建议迁移前整理目录清单,明确每个目录的迁移方式、目标路径和是否需要停写。
| 源目录 | 目标目录 | 数据量 | 是否持续写入 | 迁移方式 |
|---|---|---|---|---|
/data/app1 |
/data/app1 |
10 TB | 是 | 全量 + 增量 |
/data/archive |
/data/archive |
50 TB | 否 | 全量 |
3.4 停写和切换窗口
如果源目录在迁移过程中仍持续写入,建议采用以下流程:
- 执行一次全量迁移。
- 在业务仍运行时执行一轮或多轮增量同步。
- 进入最终切换窗口,停止源端写入。
- 执行最后一次增量同步。
- 校验目标端数据。
- 将后续读写切换到目标集群。
4. 直接 HDFS 到 HDFS 迁移
下文以迁移源集群 /data/app1 到目标集群 /data/app1 为例。
建议为每个待迁移目录使用独立目标路径,避免多个源目录共用同一个目标目录后,在增量同步或清理时相互影响。
4.1 验证源目录可访问
在目标 BMR 集群上执行:
1hadoop fs -ls hdfs://source-nn:8020/data/app1
如果源集群使用 nameservice,可执行:
1hadoop fs -ls hdfs://source-ns/data/app1
确认可以列出源目录内容后,再执行迁移。
4.2 准备目标目录
在目标集群上创建目标父目录:
1hdfs dfs -mkdir -p /data
如果目标目录已经存在,需要先确认是否为空、是否允许合并迁移,避免覆盖已有数据。
1if hdfs dfs -test -e /data/app1; then
2 hdfs dfs -ls /data/app1
3else
4 echo "/data/app1 does not exist"
5fi
4.3 全量迁移
执行全量迁移:
1hadoop distcp \
2 -m 50 \
3 -bandwidth 50 \
4 hdfs://source-nn:8020/data/app1 \
5 /data
执行完成后,目标集群中的数据路径为:
1/data/app1
第一次全量迁移时,目标端 /data/app1 尚不存在,因此目标路径使用父目录 /data;全量迁移完成后,目标端已生成 /data/app1,后续增量同步针对 /data/app1 执行。
如果需要保留权限、属主和属组,可以增加 -p 参数:
1hadoop distcp \
2 -pugt \
3 -m 50 \
4 -bandwidth 50 \
5 hdfs://source-nn:8020/data/app1 \
6 /data
其中 -pugt 用于尽量保留属主、属组、权限和时间属性;如果不需要保留这些属性,可以不加该参数。实际支持的属性以当前 Hadoop 版本为准。
4.4 增量同步
全量迁移完成后,如果源目录仍有写入,可以使用 -update 执行增量同步。
1hadoop distcp \
2 -update \
3 -m 50 \
4 -bandwidth 50 \
5 hdfs://source-nn:8020/data/app1 \
6 /data/app1
-update 会跳过未变化的文件,仅复制新增或发生变化的文件。
如果需要让目标目录和源目录保持严格一致,可以使用 -delete 删除目标端多余文件:
1hadoop distcp \
2 -update \
3 -delete \
4 -m 50 \
5 -bandwidth 50 \
6 hdfs://source-nn:8020/data/app1 \
7 /data/app1
注意:
-delete会删除目标端对应目录中源端已不存在的文件。使用前请确认目标端对应目录仅用于当前源目录迁移,例如本文示例中的/data/app1,且没有其他业务数据或手工补录数据。首次使用建议先在测试目录验证。
4.5 最后一轮同步
在最终切换前,建议停止源端对迁移目录的写入,然后执行最后一轮增量同步。
1hadoop distcp \
2 -update \
3 -m 50 \
4 -bandwidth 50 \
5 hdfs://source-nn:8020/data/app1 \
6 /data/app1
最后一轮同步完成并校验通过后,再将后续读写切换到目标集群。
5. 数据校验
迁移完成后,需要对目标集群数据进行校验。
5.1 校验目录大小和文件数
源集群执行:
1hdfs dfs -count -h /data/app1
目标集群执行:
1hdfs dfs -count -h /data/app1
对比目录数、文件数和总大小。
如果是直接跨集群访问,也可以在目标集群上分别执行:
1hadoop fs -count -h hdfs://source-nn:8020/data/app1
2hdfs dfs -count -h /data/app1
5.2 校验权限
如果迁移时保留了权限、属主或属组,需要抽查目标端权限是否符合预期。
1hdfs dfs -ls /data/app1
6. 常见问题
Q1:迁移时应该使用源集群 IP 还是 nameservice?
如果源集群是 HA 集群,优先使用 nameservice,例如:
1hdfs://source-ns/data/app1
如果无法使用 nameservice,需要确认使用的是当前 Active NameNode 地址。
Q2:如果源集群和目标集群的 nameservice 都是 bmr-cluster 怎么办?
如果两个集群的 nameservice 相同,不建议在同一个客户端中同时使用 hdfs://bmr-cluster/... 表示源端和目标端。客户端会根据本地 core-site.xml 和 hdfs-site.xml 解析 bmr-cluster,同名时无法区分源集群和目标集群。
建议为源集群配置临时 nameservice 别名,例如 source-bmr-cluster,再执行 DistCp。目标集群仍使用本地默认 HDFS 路径,例如 /data/app1。
临时配置示例,实际配置值以源集群 hdfs-site.xml 中的 NameNode ID 和 RPC 地址为准。不要直接覆盖目标集群现有 dfs.nameservices,应在现有值基础上追加源集群临时别名。建议先将目标集群当前 core-site.xml 和 hdfs-site.xml 复制到单独的客户端配置目录,再追加源集群临时 nameservice 配置,并在迁移命令中通过 HADOOP_CONF_DIR 指向该目录,避免影响集群默认配置:
1<property>
2 <name>dfs.nameservices</name>
3 <value>bmr-cluster,source-bmr-cluster</value>
4</property>
5
6<property>
7 <name>dfs.ha.namenodes.source-bmr-cluster</name>
8 <value>nn1,nn2</value>
9</property>
10
11<property>
12 <name>dfs.namenode.rpc-address.source-bmr-cluster.nn1</name>
13 <value>source-nn1-host:8020</value>
14</property>
15
16<property>
17 <name>dfs.namenode.rpc-address.source-bmr-cluster.nn2</name>
18 <value>source-nn2-host:8020</value>
19</property>
20
21<property>
22 <name>dfs.client.failover.proxy.provider.source-bmr-cluster</name>
23 <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
24</property>
迁移命令示例:
1HADOOP_CONF_DIR=/path/to/migration-conf hadoop distcp \
2 -m 50 \
3 -bandwidth 50 \
4 hdfs://source-bmr-cluster/data/app1 \
5 /data
如果后续执行增量同步,目标路径按前文示例使用 /data/app1。
注意:临时别名只用于迁移客户端侧区分源集群,不需要修改源集群自身的 nameservice。
Q3:是否必须停写才能迁移?
不一定。可以先在业务运行期间执行全量迁移和多轮增量同步,最终切换前再短暂停写并执行最后一轮增量同步。
Q4:什么时候可以使用 -delete?
仅当目标端对应目录只用于当前源目录迁移,并且确认目标端不包含额外数据时,才建议使用 -delete。例如本文示例中,需要确认 /data/app1 仅用于该源目录迁移。
Q5:目标端目录已经存在怎么办?
需要先确认目标目录是否为空、是否允许合并迁移。如果不确定,建议先恢复到临时目录,校验后再调整路径。
Q6:迁移速度慢怎么办?
可以从以下方面排查:
- 调整
-m增加或降低并发。 - 调整
-bandwidth。 - 检查源集群和目标集群 NameNode 压力。
- 检查网络带宽和丢包情况。
- 检查是否存在大量小文件。
评价此篇文章
