Hub documentation

将数据迁移到存储桶

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

将数据迁移到存储桶

本指南演示如何将大型数据集从当前位置(本地磁盘、其他云或 Hub)迁移到 Storage Bucket。请在下表中找到您的数据源,并跳转到相应章节。

在可能的情况下,将数据以文件系统形式进行读取,并运行 hf sync。它会在客户端进行去重,因此上传的字节数少于直接复制。

概览

您的数据现在位于推荐替代方案
本地磁盘或集群文件系统hf sync—
AWS S3 或 S3 兼容(R2、MinIO)使用 mount-s3 挂载,然后运行 hf sync通过 S3 网关使用 rclone
Google Cloud Storage使用 gcsfuse 挂载,然后运行 hf syncrclone,或一个 Job
Azure Blob 存储使用 blobfuse2 挂载,然后运行 hf syncrclone,或一个 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)。在大规模运行之前,请审查这些命令。

  1. 安装 CLI。 Xet 客户端随附提供。

    curl -LsSf https://hf.co/cli/install.sh | bash
    hf version
  2. 使用具有 Write 权限的令牌 登录(创建一个):

    hf auth login
    hf auth whoami
  3. 创建目标存储桶。 <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>/data

hf 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_xet 1.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 到存储桶的大规模复制:

  1. 使用 Hugging Face 登录。
  2. 输入 S3 源前缀、目标存储桶以及您的 AWS 凭证。对于允许匿名读取的公共存储桶,请开启 Public bucket:无需提供 AWS 凭证,Jobs 将以无签名方式读取 S3。
  3. Analyze 会执行一次低成本的试运行,用于检查访问权限、检测源区域并推荐配置。如果目标存储桶不存在,它将创建该存储桶(私有)。
  4. 点击 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 集成。

不要通过挂载点执行批量数据导入。hf-mount 会将写入操作暂存到磁盘缓存中(默认为 /tmp/hf-mount-cache),通过它进行大规模迁移可能会占满该磁盘。请使用上述任一方法将数据写入存储桶。如果必须通过挂载点写入大量数据,请将缓存指向一个有充足可用空间的磁盘:hf-mount start --cache-dir /mnt/big bucket <namespace>/<bucket> /mnt/data(该参数需置于 bucket 之前)。

Update on GitHub