[实战] 50TB 数据“物理导入” RustFS/S3 失败后,我如何用 Localhost 跑满 IO?

背景

最近在负责一个数据存储平台的搭建,底层存储选型使用了 RustFS (一个兼容 S3 协议的分布式文件系统)。我们面临一个棘手的初始化问题:

手里有 50TB 的历史存量数据,静静地躺在服务器的硬盘目录里。

现在的挑战是: 如何把这 50TB 数据"灌"进 RustFS 的 Bucket 里?

  • 方案 A (HTTP 上传): 走网页端或公网 API?50TB 传到猴年马月,且容易受网络波动影响。
  • 方案 B (物理 Copy): 既然数据和服务都在同一台机器上,我能不能直接 cp 到 RustFS 的数据目录,然后让它自己"扫描"一遍?

我本能地觉得 方案 B 才是正解,简单粗暴且高效。于是,我决定给开源社区提个 Issue。


一:向官方提 Feature Request

我满怀信心地去 GitHub 提了一个 Issue,希望能支持 "Sideloading" (侧载)"Bulk Import" (批量导入) 功能。

我的理由很充分:

"We physically copy the data files directly into the underlying rustfs data directory... run a CLI command to scan... rustfs indexes these files."

(我们直接物理复制文件到底层目录,然后运行 CLI 命令扫描,建立索引。)

然而,官方 Maintainer 的回复给我的想法判了"死刑":

Official Reply:

"The best way to sync a local file system to object storage is by using the mc mirror command. This approach is highly efficient... Initial Upload performs full synchronization..."

翻译一下就是: 不支持物理扫描,也不会支持。请走标准协议,用 mc mirror 工具来同步。

二:为什么不能直接 Copy?(技术复盘)

冷静下来分析,我明白了官方的苦衷。这涉及到 对象存储 vs 文件系统 的核心架构差异:

  1. 元数据 (Metadata) 是关键: 对象存储(如 MinIO, RustFS)不只是把文件存进硬盘,还需要生成配套的元数据(ETag, VersionID, Content-Type 等)。
  2. 物理 Copy 的盲区: 如果我直接 cp video.mp4 到底层磁盘,RustFS 的数据库里并没有这个文件的记录。对于系统来说,这个文件是"隐形"的,甚至可能被当做垃圾数据清理掉。
  3. 一致性: 强制要求走 S3 协议,是为了保证数据和元数据的一致性。

三:最终方案 ------ Localhost 回环加速

既然必须走 API,那就在 "网络路径" 上做文章。

虽然官方说要用客户端传,但谁规定客户端必须在千里之外?我直接在服务端本机装一个客户端,走 127.0.0.1 传输!

1:方案优势
  • 0 网络延迟: 流量不经过交换机和路由器,全部在服务器内部的回环接口(Loopback)消化。
  • 速度极快: 瓶颈只在于磁盘 I/O 和 CPU,基本能跑满硬盘读写速度。
  • 协议合规: 走了标准的 S3 协议,RustFS 能正常生成元数据。
2:实施步骤

1. 安装 MinIO Client (mc)

虽然服务端是 RustFS,但 S3 协议是通用的,mc 是目前最好用的 S3 命令行工具。

bash 复制代码
curl https://dl.min.io/client/mc/release/linux-amd64/mc \
  --create-dirs -o $HOME/minio-binaries/mc
chmod +x $HOME/minio-binaries/mc
export PATH=$PATH:$HOME/minio-binaries/

2. 配置本地别名 (关键)

注意 API 地址填 127.0.0.1

bash 复制代码
# mc alias set <别名> <API地址> <AK> <SK>
mc alias set local_rustfs http://127.0.0.1:9000 my_access_key my_secret_key

3. 执行"镜像"同步

假设我的源数据在 /data/source_50tb,我想把它放到 Bucket 的同名目录下。

bash 复制代码
# 核心命令
# --limit-upload: 稍微限制一下,避免把服务器卡死
# nohup: 放在后台跑,防止断连
nohup mc mirror /data/source_50tb local_rustfs/my-bucket/source_50tb > migration.log 2>&1 &

技巧:在目标路径末尾加上 /source_50tb,mc 会自动在 Bucket 里创建这个子目录层级,保持结构整洁。


四:致命的"空间陷阱" (避坑指南)

在执行之前,我意识到了一个极其严重的问题:磁盘空间够不够?

  • mc mirror (复制模式): 会保留源文件,传输峰值需 100TB 空间(50TB 源数据 + 50TB 目标数据)。
  • rclone move (搬家模式): 边传边删,磁盘始终维持在 50TB 左右

对于空间紧张的服务器,必须使用 rclone move。以下是具体实操:

4.1 快速配置 Rclone (连接本机)

我们不需要进入繁琐的交互式菜单,直接用一行命令生成配置。
关键点: endpoint 必须指向 127.0.0.1 以走回环网络。

bash 复制代码
# 1. 安装 Rclone (如果还没装)
curl https://rclone.org/install.sh | sudo bash

# 2. 一键生成配置 (避免手填出错)
# 别名: local_rustfs
# 类型: s3
# 厂商: Minio (RustFS/Ceph 等兼容 S3 的都可以选这个)
rclone config create local_rustfs s3 \
    provider Minio \
    env_auth false \
    access_key_id YOUR_ADMIN_ACCESS_KEY \
    secret_access_key YOUR_ADMIN_SECRET_KEY \
    endpoint http://127.0.0.1:9000

配置完成后,建议运行 rclone lsd local_rustfs: 测试一下能不能列出 Bucket。

4.2 执行"搬家"操作

配置通了之后,就可以执行 Move 操作了。记得加上 --transfers 提高并发,压榨本机 I/O 性能。

bash 复制代码
# 核心命令:Move (上传成功即删除源文件)
# --transfers=32: 开启 32 线程并发 (视磁盘性能调整)
# --progress: 显示实时进度条
rclone move /data/source_50tb local_rustfs:my-bucket/source_50tb \
    --transfers=32 \
    --progress

⚠️ 高危操作提醒:
rclone move不可逆 的(源文件会被删)。建议先在 /data/source_50tb 里找个只有几 MB 的子目录测试一下,确认文件成功出现在 RustFS 且本地被删除后,再跑全量。


五:进阶玩法 ------ 使用 --watch 实现"不停机迁移"

如果你的磁盘空间充裕,或者需要解决"旧系统还在持续产生数据"的问题,官方 Maintainer 提到的 mc mirror --watch 是一个非常高阶的建议。

场景痛点:

传输 50TB 数据可能需要好几天。在这几天里,如果你的旧业务系统还在往 /data/source_50tb 里写新文件,怎么办?等全量跑完,数据又不对齐了。

解决方案:

我们可以利用 --watch 参数,启动一个"实时监听"进程。它会监控文件系统的 INOTIFY 事件,一旦本地有新文件生成,毫秒级同步到 RustFS。

操作姿势:

建议采用 "全量 + 增量" 的组合拳:

  1. 先跑全量(追历史数据):
    使用不带 --watch 的命令,先把存量数据搬完(或者用 Rclone 搬完历史数据)。
  2. 再跑增量(追实时数据):
    全量结束后,挂起一个监听进程,保持两边数据一致,直到业务正式切换。
bash 复制代码
# 持续监听模式
# 一旦 /data/source_50tb 有变动,立刻同步
mc mirror --watch /data/source_50tb local_rustfs/my-bucket/source_50tb

总结

面对大数据量的初始化迁移,这次折腾让我总结出几条铁律:

  1. 不要幻想物理 Copy: 除非你是文件系统开发者,否则绕过 S3 协议会导致元数据丢失。
  2. 善用 Localhost: 只要客户端和服务端在一起,S3 协议也可以很快。
  3. 算好磁盘账: 空间够大用 mc mirror(稳),空间不够用 rclone move(险,但省空间)。
  4. 目录结构: 想要保持目录层级,记得在命令的目标路径上把文件夹名字加上。
相关推荐
littlegirll1 天前
一个KADB使用gpbackup迁移数据的脚本
数据库·数据迁移·kadb·gpbackup
分布式存储与RustFS2 天前
RustFS在AI场景下的实测:从GPU到存储的完整加速方案
开发语言·人工智能·rust·对象存储·企业存储·rustfs·minio国产化替代
云存储小天使2 天前
迁移上云腾讯云 COS 全指南:方案选择与实施策略
腾讯云·对象存储·数据迁移
分布式存储与RustFS3 天前
MinIO社区版“躺平”,RustFS能接棒吗?
rust·开源项目·对象存储·企业存储·rustfs·minio国产化替代
飞翔沫沫情5 天前
MinIO 新版本 Docker 部署指南:告别 Web 控制台,拥抱 CLI 管理
docker·容器·docker-compose·对象存储·minio
飞翔沫沫情8 天前
记一次 minio 排障
对象存储·minio
Miya_Ye10 天前
SeedWeedfs学习
对象存储·seedweedfs
晓时谷雨11 天前
达梦数据库适配方案及总结
数据库·达梦·数据迁移
分布式存储与RustFS13 天前
担心 MinIO 维护影响业务?三行配置实现到 RustFS 的无感切换
开源·对象存储·minio·企业存储·rustfs
云存储小天使18 天前
让 AI 更普惠:向量存储桶为海量 AI 记忆提供高性价比的 “数字基石”
腾讯云·对象存储·向量存储桶