Hub documentation
将数据迁移到存储桶
将数据迁移到存储桶
本指南演示如何将大型数据集从当前位置(本地磁盘、其他云或 Hub)迁移到 Storage Bucket。请在下表中找到您的数据源,并跳转到相应章节。
在可能的情况下,将数据以文件系统形式进行读取,并运行 hf sync。它会在客户端进行去重,因此上传的字节数少于直接复制。
概览
| 您的数据现在位于 | 推荐 | 替代方案 |
|---|---|---|
| 本地磁盘或集群文件系统 | hf sync | — |
| AWS S3 或 S3 兼容(R2、MinIO) | 使用 mount-s3 挂载,然后运行 hf sync | 通过 S3 网关使用 rclone |
| Google Cloud Storage | 使用 gcsfuse 挂载,然后运行 hf sync | rclone,或一个 Job |
| Azure Blob 存储 | 使用 blobfuse2 挂载,然后运行 hf sync | rclone,或一个 Job |
| Hub 仓库或其他存储桶 | hf buckets cp(服务端) | — |
| 非常大的 S3 前缀 | hf-s3ream(alpha) | 挂载 + hf sync,按子路径拆分 |
为什么 hf sync 是默认选项:
- 您上传的数据更少。
hf sync通过 Xet 客户端进行上传,该客户端会先对数据进行分块和去重,因此只会发送 Hub 尚未见过的数据块。而原始复制(例如通过 S3 网关使用 rclone)则会传输每一个字节。 - 速度至少不慢。 在我们目前支持的迁移中,通过挂载源使用
hf sync的吞吐量与 rclone 相当或更优。
开始之前
本指南中的所有命令均使用 hf,即 Hugging Face CLI。其帮助输出可供智能体读取,因此编码智能体可以为您组装并监控迁移过程(参见 面向 AI 智能体的 CLI)。在大规模运行之前,请审查这些命令。
安装 CLI。 Xet 客户端随附提供。
curl -LsSf https://hf.co/cli/install.sh | bash hf version
使用具有 Write 权限的令牌 登录(创建一个):
hf auth login hf auth whoami创建目标存储桶。
<namespace>是您的用户名或组织名称。如果不指定--region,存储桶将创建在该命名空间的默认 存储区域 中,对于 Team & Enterprise 计划以外的用户,该区域始终为美国。对于这些计划,请传入--region us或--region eu进行选择。hf buckets create <namespace>/<bucket> --private
先进行一次测试运行。无论采用哪种路径,都请先在一个小子集(一个文件夹,或一个
--include模式)上演练,使用--dry-run和hf buckets ls检查结果,然后再启动完整的迁移。本指南中的每条路径都支持断点续传,因此测试运行不会带来任何额外成本。
从本地磁盘或集群文件系统
当您的数据位于本地磁盘、挂载的卷或集群临时存储(scratch)上时,请使用此方法:任何机器可以以文件形式读取的位置均可。对于下文中的每种云路径,一旦源端完成挂载,这也是最后一步。
hf sync ./data hf://buckets/<namespace>/<bucket>/datahf sync 会对比源和目的地,仅传输差异部分,因此重新运行相同命令即可恢复中断的迁移:已上传的文件会被跳过。常见变体:
# Mirror exactly: also delete destination files that are gone from the source
hf sync ./data hf://buckets/<namespace>/<bucket>/data --delete
# Preview what would transfer, without uploading
hf sync ./data hf://buckets/<namespace>/<bucket>/data --dry-run
# Only some files
hf sync ./data hf://buckets/<namespace>/<bucket>/data --include "*.parquet" --exclude "tmp/*"要在运行前审查大型迁移,请将计划写入文件,检查后再应用。这样只需扫描一次源和目的地,而不是在试运行和正式运行时各扫描一次。
hf sync ./data hf://buckets/<namespace>/<bucket>/data --plan plan.jsonl # scan once, write the plan
hf sync --apply plan.jsonl # run exactly that plan请在创建计划的目录中运行 --apply,因为计划会记录您输入的源路径。--apply 不会检查已上传的内容,因此若要恢复中断的运行,请重新运行普通的 hf sync 命令。
要验证这一点,请检查试运行是否没有剩余待传输的内容,并抽查其内容:
hf sync ./data hf://buckets/<namespace>/<bucket>/data --dry-run
hf buckets ls hf://buckets/<namespace>/<bucket>/data调优
- 将缓存保留在高速磁盘上。Xet 客户端会在
HF_HOME下缓存数据块和去重索引(即分片缓存)。如果您的主目录不在 NVMe 上,请将HF_HOME指向本地 NVMe。 - 在资源充足的机器上执行批量迁移时,请开启高性能模式。
HF_XET_HIGH_PERFORMANCE=1会提高并发数、缓冲区大小以及同时摄取的文件数量,使客户端能够利用所有 CPU 核心并打满网络带宽。该模式适用于高带宽、快速磁盘的机器;在使用hf_xet1.7.0 之前的版本时,请确保至少配备 64 GB 内存(可通过hf env查看当前配置)。请参阅 环境变量。 - 限制分片缓存的大小。其大小限制是软性的:缓存仅在一次运行的开始时被修剪,因此在一次较长的运行过程中,它可能会远远超过该限制。在大规模迁移中,尤其是在高性能模式下,它可能会增长到数百 GB 并占满磁盘,从而导致运行中止。请将
HF_XET_SHARD_CACHE_SIZE_LIMIT设置为明显低于您的可用磁盘空间,但不要低于您的实际需求:大小为 X 的缓存大约可以对 1000 × X 的数据进行去重。请参阅 分片缓存。
在开始同步之前设置这些参数。大小接受人类可读的值,例如 64gb:
export HF_HOME=/mnt/nvme/hf # chunk and shard caches on NVMe
export HF_XET_HIGH_PERFORMANCE=1 # use all cores and the full network
export HF_XET_SHARD_CACHE_SIZE_LIMIT=64gb # keep the shard cache under free disk space
hf sync ./data hf://buckets/<namespace>/<bucket>/data按子路径拆分(实验性)
对于非常大的数据集,您可以将源拆分为子路径,并同时运行多个 hf sync 进程。早期测试表明吞吐量大致呈线性扩展,但这需要进一步验证。两条规则:
- 按相关数据拆分,以便每个工作进程的文件之间能够良好地去重。
- 为每个 worker 设置独立的
HF_HOME,以避免它们争用缓存。由于每个缓存都会占用磁盘空间,请在各 worker 之间分配HF_XET_SHARD_CACHE_SIZE_LIMIT。
HF_HOME=/mnt/nvme/hf-a hf sync ./data/groupA hf://buckets/<namespace>/<bucket>/groupA &
HF_HOME=/mnt/nvme/hf-b hf sync ./data/groupB hf://buckets/<namespace>/<bucket>/groupB &
wait单个进程共享一个缓存,去重效果最佳,因此仅当一个进程无法充分利用网络时才进行拆分。
故障排除
| 症状 | 修复 |
|---|---|
401 或身份验证错误 | 使用 Write 令牌运行 hf auth login,并使用 hf auth whoami 进行验证。 |
| 比预期更慢 | 将 HF_HOME 放置在 NVMe 上,设置 HF_XET_HIGH_PERFORMANCE=1,并在靠近数据的位置运行。 |
| 运行因磁盘已满错误而中止 | 分片缓存已占满磁盘。请将 HF_XET_SHARD_CACHE_SIZE_LIMIT 设置为低于您的可用空间,或将 HF_HOME 移至更大的磁盘。 |
| 传输已中断 | 重新运行相同的 hf sync 命令。已上传的文件将被跳过。 |
从 AWS S3 或 S3 兼容存储
hf sync doesn’t read s3:// URLs, so mount the source bucket as a filesystem with Mountpoint for Amazon S3, then sync from the mount. Your data still goes through the Xet client, so you get client-side deduplication.
mount-s3 my-source-bucket /mnt/src
hf sync /mnt/src hf://buckets/<namespace>/<bucket>
umount /mnt/src对于 Cloudflare R2 或 MinIO 等兼容 S3 的存储,请在 mount-s3 中添加 --endpoint-url <url>。对于允许匿名读取的公共存储桶(例如 AWS Open Data registry 中的存储桶),请添加 --no-sign-request。验证、调优和故障排除与 本地数据 相同。
替代方案:通过 S3 网关使用 rclone
如果您已经在运行 rclone 且不希望使用挂载,请使用此方法。权衡之处在于:rclone 会将每个字节都通过 S3 网关 传输,且没有客户端去重,因此传输的数据量比 hf sync 更多。您需要为网关提供 S3 凭证。
请使用 rclone 1.70 或更高版本(可通过
rclone version检查,并从 rclone downloads 升级)。旧版本在列出非常大的存储桶时可能会耗尽内存。旧的建议通常推荐使用--fast-list;使用较新版本的 rclone 时不需要该选项,而且在处理海量列表时,它会将所有内容保留在内存中,可能导致同样的故障。
在 ~/.config/rclone/rclone.conf 中,将网关添加为远程,与源远程(如下面的 aws)并列:
[hf]
type = s3
provider = Other
endpoint = https://s3.hf.co/<namespace>
access_key_id = HFAK...
secret_access_key = ...
region = us-east-1
force_path_style = true
list_version = 2
upload_cutoff = 256M
chunk_size = 256M网关仅支持 ListObjectsV2,因此必须设置 list_version = 2。使用 256M 分片时,大文件所需的分片数量远少于 rclone 默认的 5M 分片。rclone 每次传输在内存中保留 4 个分片,因此下文中的 --transfers 16 大约需要 16 GB 的内存;在内存较小的机器上请降低该值。然后执行复制并检查:
rclone copy aws:my-source-bucket hf:<bucket> --transfers 16 --checkers 16 --progress rclone check aws:my-source-bucket hf:<bucket>
rclone copy 仅传输缺失或已更改的对象,因此可以安全地重新运行以恢复。在进行大规模导入之前,请阅读网关限制,特别是对象键命名规则。
从 Google Cloud Storage 或 Azure Blob Storage
与 S3 相同的方法:使用其云自身的驱动程序挂载源,然后运行 hf sync。
Google Cloud Storage:使用 gcsfuse 进行挂载。
gcsfuse my-gcs-bucket /mnt/src
hf sync /mnt/src hf://buckets/<namespace>/<bucket>Azure Blob Storage:使用 blobfuse2 进行挂载。配置文件用于指定存储账户和容器。
blobfuse2 mount /mnt/src --config-file=./blobfuse2.yaml
hf sync /mnt/src hf://buckets/<namespace>/<bucket>如果没有挂载,你可以使用 rclone(它原生支持读取 GCS 和 Azure;复用上述的 hf 远程,具有相同的无去重权衡),或者将迁移作为 Job 运行。
在后台使用 Jobs 运行迁移
Jobs 在 Hugging Face 的计算资源上运行脚本:你可以选择硬件,通过 CLI 启动,并且 按分钟计费。当你希望长时间、多 TB 的迁移任务在无人值守的情况下运行,而不是在笔记本电脑上或需要保持打开的会话中运行时,可以使用它。
1. 编写迁移脚本(migrate.py)。此示例通过 Xet 客户端将 S3 前缀中的每个对象复制到存储桶中,因此写入操作会进行去重。它适用于一次性复制中等规模的前缀;对于非常大的前缀,请参阅 hf-s3ream。请调整顶部的配置:
# /// script
# dependencies = ["huggingface_hub", "boto3", "tqdm"]
# ///
import boto3
from botocore import UNSIGNED
from botocore.config import Config
from huggingface_hub import HfFileSystem
from tqdm.contrib.concurrent import thread_map
# --- adapt these ---
SRC_BUCKET = "my-source-bucket"
SRC_PREFIX = "some/prefix/"
DST = "buckets/<namespace>/<bucket>"
WORKERS = 8 # files copied in parallel
# -------------------
s3 = boto3.client("s3") # AWS credentials come from the Job's secrets
# For a public bucket (for example from the AWS Open Data registry), read anonymously
# instead, and drop the AWS secrets from the launch command:
# s3 = boto3.client("s3", config=Config(signature_version=UNSIGNED))
fs = HfFileSystem() # HF token comes from the Job's HF_TOKEN secret
# List the destination once: {path: size} of the files already copied
done = {path: info["size"] for path, info in fs.find(DST, detail=True).items()}
# List the source and keep the objects not copied yet
todo = []
pages = s3.get_paginator("list_objects_v2").paginate(Bucket=SRC_BUCKET, Prefix=SRC_PREFIX)
for page in pages:
for obj in page.get("Contents", []):
key = obj["Key"]
if key.endswith("/"):
continue # folder marker: bucket keys can't end with "/"
if done.get(f"{DST}/{key}") != obj["Size"]:
todo.append(key)
def copy(key):
body = s3.get_object(Bucket=SRC_BUCKET, Key=key)["Body"]
with fs.open(f"{DST}/{key}", "wb") as out:
for chunk in iter(lambda: body.read(64 << 20), b""):
out.write(chunk)
# Copy WORKERS files at a time, with a progress bar
thread_map(copy, todo, max_workers=WORKERS)- 每个对象都会暂存到 Job 的磁盘上,并在关闭时上传,因此磁盘必须能够同时容纳
WORKERS个最大对象。若要加速处理大量小对象,请调高WORKERS;对于非常大的对象,则应调低该值。 - 桶中已存在且大小相同的文件会被跳过,因此重新运行脚本可以从中断处恢复复制操作。如果源文件内容已更改但大小保持不变,脚本不会重新复制该文件:若要使桶与不断变化的源保持同步,请改为挂载源并运行
hf sync。
对于 GCS 或 Azure,请将 boto3 替换为相应云服务的 SDK(google-cloud-storage、azure-storage-blob),并调整列表和读取调用。目标端部分保持不变。
2. 将其作为后台作业启动,并将您的凭据作为机密信息传入:
hf jobs uv run --detach --flavor cpu-performance --timeout 24h \
--secrets HF_TOKEN \
--secrets AWS_ACCESS_KEY_ID \
--secrets AWS_SECRET_ACCESS_KEY \
migrate.py每个 --secrets NAME 都会从您的环境中传递该变量的值(对于 HF_TOKEN,如果未设置,则使用您已登录的令牌)。任务默认在 30 分钟后停止,因此请将 --timeout 设置得足够长以覆盖整个传输过程;如果任务提前停止,请重新启动它,它将跳过已复制的文件。
--detach 会立即返回一个 Job ID。使用 hf jobs logs -f <job_id> 跟踪进度,使用 hf jobs ls 列出运行记录,使用 hf jobs hardware 查看硬件选项。
从 Hub 仓库或其他存储桶
如果数据已经位于 Hub 上,例如在模型或数据集仓库或其他存储桶中,请在服务器端进行复制。对于仅由 Xet 跟踪的文件,只会移动内容哈希,因此复制几乎是瞬间完成的,且不会重新上传任何内容。
# From a dataset repository into a bucket
hf buckets cp hf://datasets/<org>/<dataset>/<path> hf://buckets/<namespace>/<bucket>/<path>
# From one bucket to another
hf buckets cp hf://buckets/<namespace>/<bucket-a>/<path> hf://buckets/<namespace>/<bucket-b>/<path>- 源和目标必须位于同一存储区域。
- 您需要对源具有读取权限,对目标具有写入权限。
- 未被 Xet 跟踪的小型文件(如配置文件、README)会自动下载并重新上传。
- 从存储桶复制回仓库的功能目前尚不可用,但已列入开发计划。
有关 Python 等效操作,请参阅 在仓库和存储桶之间复制文件。
使用 hf-s3ream 处理非常大的 S3 前缀
hf-s3ream 是一个早期(alpha)阶段的社区工具,并非 Hugging Face 官方支持的产品。在进行大规模迁移之前,请先在较小的前缀上对其进行测试。
hf-s3ream(GitHub 上的源代码,Apache-2.0)通过 Web 界面执行从 S3 到存储桶的大规模复制:
- 使用 Hugging Face 登录。
- 输入 S3 源前缀、目标存储桶以及您的 AWS 凭证。对于允许匿名读取的公共存储桶,请开启 Public bucket:无需提供 AWS 凭证,Jobs 将以无签名方式读取 S3。
- Analyze 会执行一次低成本的试运行,用于检查访问权限、检测源区域并推荐配置。如果目标存储桶不存在,它将创建该存储桶(私有)。
- 点击 Run 可启动规划器任务。规划器会构建基于范围的复制计划,启动复制器任务,并在实时图表上显示进度。即使关闭标签页,复制操作仍会继续运行,但页面将无法重新连接到该任务。若要停止复制,请单击 Stop copy,或取消规划器任务(
hf jobs cancel <planner-job-id>):规划器会随之取消其复制器。
hf-s3ream 在您的账户下运行于 Jobs,因此相关费用将计入您的账户。仅允许来自私有网络(VPC)访问的 S3 存储桶无法从 Jobs 访问。
在哪里运行大型迁移
对于多 TB 规模的迁移,通常会在云虚拟机上而非笔记本电脑上运行传输任务。如果您不想自行管理虚拟机,可以将其作为 Job 运行。
- 在与源相同的云和区域中运行。通过本地网络读取源数据是最快且成本最低的方式,而从源云产生的出站流量通常是最主要的成本。随后,上传将通过互联网传输至 Hugging Face(美国区域位于 AWS
us-east-1)。 - 使用单进程多线程。 高性能模式下的单个
hf sync共享同一个去重缓存。仅当单个进程无法充分利用网络带宽时,才按子路径拆分。 - 保持长时间运行的任务存活。 通过 SSH 连接时,请在
tmux(或screen、nohup)中启动迁移,以确保会话断开后任务仍能继续运行:执行tmux new -s migrate,按 Ctrl-b 然后按 d 分离会话,之后可通过tmux attach -t migrate重新连接。
用于在测试运行中验证的初始规模设置:
| 资源 | 指导 | AWS 示例 | GCP 示例 |
|---|---|---|---|
| 磁盘 | HF_HOME 使用本地 NVMe,且可用空间需高于分片缓存上限。请勿将网络附加磁盘用作缓存。 | 实例存储 NVMe(c7i/m7i d 变体,或 i4i) | n2 或 c3 虚拟机上的本地 SSD |
| CPU | 许多 vCPU:客户端在 CPU 上对数据进行分块和哈希处理。 | c7i.8xlarge 或更大 | c3-standard-22 或更大 |
| 内存 | 高性能模式的缓冲区空间充足;在 1.7.0 之前,使用 hf_xet 时至少需要 64 GB。 | — | — |
| 网络 | 到互联网的高带宽(25 Gbps 级别)。 | — | — |
后续步骤
- 就地使用数据。使用 hf-mount 将存储桶挂载为本地文件系统,或作为 Jobs 和 Spaces 中的卷。
- 直接从您的工具中读取。pandas、Dask、PyArrow、Daft、DuckDB、🤗 Datasets 和 Spark 可以直接读取
hf://buckets/...路径。请参阅 Bucket 集成。
Update on GitHub不要通过挂载点执行批量数据导入。hf-mount 会将写入操作暂存到磁盘缓存中(默认为
/tmp/hf-mount-cache),通过它进行大规模迁移可能会占满该磁盘。请使用上述任一方法将数据写入存储桶。如果必须通过挂载点写入大量数据,请将缓存指向一个有充足可用空间的磁盘:hf-mount start --cache-dir /mnt/big bucket <namespace>/<bucket> /mnt/data(该参数需置于bucket之前)。