Xet 已登陆 Hub

发布于 2025 年 3 月 18 日
在 GitHub 上更新
想跳过细节,直接体验前所未有的更快上传下载和更大文件支持吗?

点击这里了解如何加入 Xet 等候名单(或直接前往此处立即加入)。

在过去几周里,Hugging Face 的 Xet 团队迈出了重要一步,将首批模型和数据集仓库从 LFS 迁移到了 Xet 存储

这是实现 Hugging Face 对 Hub 的愿景的众多步骤之一,旨在赋能 AI 构建者更有效地构建、迭代和协作处理海量模型和数据集。如果您对技术本身的深入探讨感兴趣,请查看以下文章:

但这篇博文并非关于核心技术,而是揭秘 Xet 登陆 Hub 幕后的故事,带您了解从概念验证到首批仓库迁移的全过程。

这次迁移将 Hub 约 6% 的下载流量转移到了 Xet 基础设施上,验证了几个关键组件,并测试了与各种仓库访问方式(例如,通过本地开发环境、不同的库、CI 系统、云平台等)的集成。对于拥有近两百万开发者和超过两百万个公开仓库的平台来说,真实世界的使用是最终的试验场。设计像 Xet 存储这样复杂的系统需要权衡多方因素。你需要为规模、性能和可靠性做规划,但一旦字节开始流动,挑战便会浮现。关键在于知道何时从设计和理论转向实践。

Xet 的不同之处

LFS 是目前仓库背后的存储系统,它将大文件存储在仓库之外的一个独立的对象存储中。LFS 在文件级别进行去重。即使是微小的编辑也会创建一个需要完整上传的新版本,这对于许多 Hub 仓库中数 GB 大小的文件来说是十分痛苦的。

相比之下,Xet 存储使用基于内容的数据分块 (CDC) 技术,在字节级别(约 64KB 的数据块)进行去重。如果您在 Parquet 文件中编辑一行,或在 GGUF 模型中调整一小段元数据,只有那些发生变化的数据块会被传输。

这为大文件传输带来了显著的好处。例如,Xet 团队维护一个约 5GB 的内部 SQLite 数据库,用于驱动一个指标仪表板。使用 LFS,追加 1MB 的数据(大约是目前的平均更新量)需要重新上传整个 5GB 的文件。而使用 Xet 存储,我们只需推送新的数据。

SQLite Dedupe from one version to another
使用 dedupe_estimator(一个用于估算文件间块级别去重效果的工具)对最近两次运行进行的比较。红色数据块表示使用 Xet 时需要上传的部分。

这意味着仪表板的上传只需十分之一秒(在 50Mb/s 的速率下),而不是如果数据库由 LFS 支持所需的 13 分钟。

要实现这一点,需要以下组件之间的协调:

  1. 一个支持 Xet 的客户端
    • 将数据分割成约 64 KB 的数据块。
    • 在本地对相同的数据块进行去重,并将它们聚合成约 64 MB 的数据块后再上传。
  2. Hugging Face Hub
    • 接收客户端请求并将其路由到正确的仓库。
    • 提供认证和安全保障。
  3. 内容寻址存储 (CAS)
    • 对上传和下载强制执行基于数据块的去重。
    • 为旧的、不支持 Xet 的客户端提供一个 LFS 桥,其行为类似于传统的 LFS 服务器,并为下载提供单一 URL。
  4. Amazon S3
    • 存储文件内容(数据块)和文件重构元数据(分片)。
    • 提供 CAS 引用的最终持久化数据层。

在进入生产环境之前,该系统被部署到一个临时环境中,我们在其中构建了一个核心功能链路,以支持通过 huggingface_hub 进行上传和下载。下面的视频展示了我们一个月后的进展:

在快速完成概念验证的兴奋之后,团队开始着手解决与 Hub 这个复杂生态系统之间棘手的集成问题(隐私、向后兼容性、碎片化等)。最终,该基础设施进入了供 Hugging Face 团队成员使用的生产环境。随着真实使用数据的不断涌入,我们推进了首次大规模迁移。

迁移日

2 月 20 日上午 10 点,全体人员严阵以待。在此前的几周里,团队已经构建了内部工具,用于将文件从 LFS 迁移到 Xet,同样重要的是,在必要时可以将仓库回滚到 LFS。现在是检验成果的时候了。Grafana 和 Kibana 上亮起了新的日志和指标,实时显示着负载的转移情况。

Grafana the day of the migration
Grafana 中进入 Xet 的请求视图。

Kibana 中的情况也一样,只是在这里你能看出我们什么时候去吃了午饭。

Grafana the day of the migration
Kibana 中进入 Xet 的请求视图。

到当天结束时,我们成功地将所有目标仓库迁移完成,总共 4.5 TB 的数据进入了 Xet 存储。每个仓库的下载现在都由我们的基础设施提供服务。

迁移后的挑战

没有哪次发布是没有教训的。系统平稳地处理了负载,迁移也没有出现任何重大中断,但随着数据流经各个组件,我们开始看到一些趋势。

数据块格式带来的下载开销

在审查迁移后的网络吞吐量时,我们发现 CAS 下载的数据量是其返回给客户端的四倍。

Grafana throughput metrics before block format change
下载量 (rx) 为黄色,发送给客户端的量 (tx) 为绿色。

经过进一步调查,我们发现绝大多数对 CAS 的请求都是针对文件内 10MB 的数据范围。这些请求来自使用 hf_transfer 加速大文件下载的用户。请求的范围与数据块边界不对齐,而且数据块格式没有提供未压缩的数据块长度,以便直接跳到数据块内的数据。相反,CAS 从头开始流式传输数据块,并一直读取直到找到请求的数据。

对于一个平均大小为 60MB 的数据块,以及多个对其内部范围的部分请求,开销会累积起来。CAS 读取了 210MB,却只交付了 60MB,下载与发送给客户端的字节比为 3.5:1。在不规则大小的数据块和可能跨越多个数据块的范围上进行扩展时,最终达到了 4:1 的下载与发送字节比。

常言道,一图胜千言:

Graphical representation of block format issue
红色块是不必要流式传输的内容,而绿色块显示了 CAS 实际请求并最终发送的数据。

为了解决这个问题,我们更新了数据块格式,以存储数据块长度的元数据,使 CAS 能够只下载每个请求实际需要的内容。这种格式更改需要跨多个组件进行协调更新:

  • CAS API
  • 数据块元数据格式
  • S3 上的 2^16 + 1 个数据块(我发誓这纯属巧合)

所有这些都是在没有停机的情况下完成的。这不仅使 CAS 下载与返回数据的比例达到了平衡,还将所有 GET 请求的延迟降低了约 35%。

Grafana throughput metrics after block format change
下载和发送数据的平衡视图,整体吞吐量有所降低。

Pod 负载不均衡

与此同时,我们还发现 CAS 集群中出现了意外的负载不均衡。一个 Pod 的活跃上传数会飙升到数百个,而其他 Pod 则以个位数的速度缓慢运行。更换负载均衡器的路由算法(从轮询到最少未完成请求)和增加更多节点在当时并没有太大效果。

深入研究后我们意识到,在上传过程中,CAS 在上传前会写入一个临时文件进行验证,但没有调用 fsync,这使得操作系统将写入操作缓存在页面缓存中。当上传请求激增时,未刷新的页面缓存会导致内存压力增加。

当操作系统试图将页面缓存刷新到磁盘时,Pod 会因块存储而经历吞吐量限制,导致上传延迟增加。在上传缓慢处理的同时,新的请求不断涌入,将更多数据推向磁盘。这形成了一个恶性循环,导致上传积压和我们在迁移期间看到的负载不均衡。

Pod load imbalance
下载和发送数据的平衡视图,整体吞吐量有所降低。

为了防止 Pod 进入这种状态,我们限制了每台机器接受的并发上传数量,在达到限制时会拒绝请求,从而将请求推送到集群中的其他 Pod。如果集群中的所有 Pod 都进入这种状态,那么我们的自动扩缩容策略就会启动。长期的解决方案可能包括强制磁盘同步、移除磁盘上的缓冲,或者切换到吞吐量更好的临时存储。

迁移的经验总结

这两个问题带来了重要的架构改进,但它们并非团队在迁移后几周内解决的唯一挑战。我们还解决了其他性能问题、一个内存泄漏(我们修复了但仍无法确定根本原因),并根据 AWS 的建议,将 LFS 桥从应用负载均衡器 (ALB) 迁移到网络负载均衡器 (NLB),以提高流量突发时的可扩展性。

经验教训

  • 没有什么能比得上生产环境:没有任何测试环境能够模拟大规模的用户行为。即使经过了仔细的集成工作和 Hugging Face 团队数月的测试,一些极端情况也只有在我们通过系统输送真实流量后才浮出水面。
  • 迁移能模拟真实流量:通过分阶段增量迁移,并在更多流量进入基础设施之前发现这些问题,我们避免了停机和中断。与从第一天起就将整个 Hub 迁移到 Xet 相比,管理一小部分流量和存储相对容易得多。
  • 积累学习成果:基础设施和系统设计在几周内通过迭代得到了强化。未来在 Xet 上的每一个字节和网络请求都将受益于这些经验教训。

简而言之,真实世界的负载对于暴露这些挑战至关重要,而增量迁移让我们能够安全地应对它们。这就是我们确保由 Xet 支持的仓库能够为整个 Hugging Face 社区可靠地扩展,实现更快的上传、更少的瓶颈和最小的中断。

准备就绪,Xet,出发!

随着初步迁移的完成,Xet 现已正式登陆 Hugging Face Hub。

Xet speed

我们正在完成与 huggingface_hub 的正式集成,这意味着您无需对当前工作流程进行重大更改即可享受 Xet 带来的好处。开始使用:

  1. 加入等候名单
    • 在这里注册,使用您的用户或组织账户(如果您有管理员/写入权限)。
    • 一旦通过,您的新仓库将自动使用由 Xet 支持的存储。
    • 我们也会迁移您现有的仓库,让您不会错过更快的传输体验。
  2. 使用您常用的工具
    • 一个名为 hf_xet 的 Python 包即将加入 huggingface_hub。如果您使用 transformersdatasets 库,它已经在使用 huggingface_hub,所以您只需在同一环境中安装 hf_xet 即可。安装步骤和文档即将发布。
    • 继续使用您已有的命令来下载和上传大文件。
  3. 享受好处
    • 减少等待上传和下载的时间,更快地迭代大文件。
    • 您团队中的每个人都应该升级到 hf_xet 以获得全部好处,但旧版客户端仍可通过 LFS 桥保持兼容。

如果您有任何问题,请在下方的评论区给我们留言 👇 或在 Xet 团队页面发起讨论。敬请期待我们推出更多功能(更快的网页上传、更快的 Git 工作流),为 Hugging Face 上的每一位 AI 构建者带来更快的大文件协作体验!

社区

注册登录以发表评论