跳到正文
北京时间
原文
Meta Engineering Blog(RSS)·· 2026-07-02精选AI 评分71

Meta 大规模 AI 存储蓝图

Meta’s AI Storage Blueprint at Scale

AI 导读

Meta 运营数百 EB 级存储集群,基于 Tectonic 分层存储层构建 BLOB 存储架构,以应对两大挑战:最大化 GPU 利用率与研究迭代速度。传统 BLOB 架构的多层元数据查询可导致数百毫秒延迟,使 GPU 因 I/O 等待停顿。新架构将训练栈逐步迁移到 BLOB 存储接口上,利用闪存提供可预测的低 pMax 延迟,避免单 GPU 慢速拖慢整批任务。同时,统一的数据湖访问支持地理分布 GPU 间的数据高速注入与跨区移动,提升研究效率。

推荐理由

Meta的存储架构复盘给出了一条明确路径,从重写元数据到分层缓存,他们把GPU利用率和研究者迭代速度同时提升了一个档次,做AI训练平台的值得细读。

正文 · AI 翻译

在过去几年里,模型能力和训练数据集规模经历了指数级增长。在过去一年左右的时间里,新前沿模型发布之间的间隔已从数月缩短到数周。可靠且快速的存储访问,对于这场 AI 创新的速度和计算成本都至关重要。如果 AI 是大脑,那么存储就是记忆:能力与速度高度依赖于记忆的规模和检索的速度。

然而,尽管 AI 算力性能大约每两年翻三倍,存储和互连性能的增长却更为温和。因此,存储瓶颈仍然是导致 AI 工作负载中 GPU 停顿的主要因素之一,直接影响支出和上市时间。除了 GPU 利用率之外,存储架构还直接影响 AI 研究的迭代速度;随着 GPU 日益地理分布式部署、数据集规模日益庞大,研究人员花费大量时间在跨区域摄取和移动数据上,从而影响了研究速度。在这篇博客文章中,我们将讨论 Meta 的 BLOB 存储架构如何演进,以应对两大主要挑战:最大化 GPU 利用率和最大化研究速度。

存储架构概览

Meta 运营着数百个 EB 级存储集群,服务于 Meta 所有对外和对内产品,包括 Facebook、Instagram、Reality Labs、Meta AI、广告、数据仓库以及内部数据库。我们的存储服务对外提供对象存储、文件系统和块设备 API,而这些 API 抽象构建在一个名为 Tectonic 的可水平扩展的基础块层之上。Tectonic 层是一个区域级、多租户的存储织构,借助纠删码技术提供高持久性和高可用性,支持跨介质类型(例如 HDD 和闪存)的分层,并管理热数据、冷数据和温数据的智能放置,以实现跨租户的 I/O 高效利用。运行在 Tectonic 之上的 BLOB 存储层则对外提供全局、可无限扩展的存储织构,并暴露相应策略,让用户可以在持久性与可用性之间进行权衡。

在此前一场题为“训练 Llama:存储视角”的 @Scale 演讲中,我们讨论了 Meta 如何通过在 Tectonic 块层之上暴露一个类 NFS 的 FileSystem 接口,直接在 Tectonic 块层上训练 Llama。尽管这一架构在 Meta 内部仍被广泛使用,但我们的现代训练栈一直在缓慢迁移到 BLOB 存储接口之上,整个行业也是如此。这一转变的动因,既在于需要对 BLOB 存储层中大规模数据湖进行统一的存储访问,也在于对高性能的需求。

最大化 GPU 利用率

现代 AI 工作负载“数据饥渴”,其负载特征与传统 Web 应用截然不同:突发且持续的高吞吐量、可预测且有界的 pMax 延迟,以及多变的 I/O 模式。近年来,BLOB 存储的关注重点已大幅转向最大化 GPU 利用率。

为什么延迟至关重要

要理解为什么有界且低 pMax 延迟如此重要,不妨以模型训练为例。在训练过程中,数十万块 GPU 会多次遍历存储中的海量数据(即经过多个 epoch),GPU 以批次方式训练数据集。每隔一定数量的 step 或 batch,GPU 之间会周期性地同步各自的状态。如果某一块 GPU 速度慢,这一步就会拖慢所有 GPU,乃至整个训练过程。

图 1 展示了跨两块 GPU 的数据加载流水线。每块 GPU 主机中的 dataloader 都会预取下一个数据集批次,而 GPU 则在处理当前批次,以实现计算与 I/O 的最大重叠。在 GPU1 的情况下,存储获取延迟完全在界限之内,因此 GPU 从不会因等待 I/O 而停滞。在 GPU2 的情况下,出现了两次存储获取高延迟,导致 GPU 停滞。这些停滞最终延迟了整体 step 的完成时间。

图 1:跨两块 GPU 的数据加载。

传统 BLOB 存储架构并未为 AI 做好准备

多年来,BLOB 存储以有机的方式演进,以真正的面向服务架构不断叠加层级。其中许多层都是有状态的,并维护着自己的元数据存储。虽然这些元数据访问延迟通常不是全球 HDD 所服务的传统用例的瓶颈,但对于需要在闪存中以毫秒级访问数据的 AI 工作负载而言,它们却是致命的障碍。图 2 展示了典型 getObject(“/bucket/path”) API 的请求流程。请求到达 API 服务器后,服务器会在 namelayer、volumeslayer 和 containerlayer 之间进行大量元数据查找,然后才能将路径解析为一组 (blockId, offset, size) 元组。其中一些查找可能跨区域进行,延迟累计达到数百毫秒并不罕见;任何一次查找出现缓慢响应就足以导致问题。查找完成后,API 服务器将数据从 Tectonic 层代理给客户端。

图 2:getObject API 的旧请求流程。

尽管这一架构很好地服务了传统工作负载,但决定设计权衡的基础假设此后已经发生了变化。其中一些包括:

  • 性能与延迟:如前所述,传统工作负载的延迟需求较为适中,而 AI 工作负载则要求一直到 pMax 都具备可预测且有界的延迟。
  • 可靠性与持久性:旧架构在设计上具备高持久性和高可用性,即使面对区域级故障也是如此;数据和元数据默认在全球范围内复制。尽管 AI 工作负载要求极高的可用性,但默认全球复制的设计选择已不再成立。
  • 成本效率:旧有技术栈构建在 HDD 之上,并针对每字节成本进行了高度优化。AI 工作负载对 IOPS 的需求使得必须采用闪存,此外,存储的计算成本相对于 GPU 的计算成本已变得微不足道。
  • 能效:有了 GPU,数据中心日益受到功耗而非空间的制约。每一千瓦用于存储的电力,就是没有用于 GPU 的电力。这是 AI 工作负载带来的新约束。

简而言之,权衡空间已经发生了足够大的变化,促使我们重新思考整个架构。

重建基础

在着手构建新基础时,我们做出了以下重大设计选择:

  • 统一元数据模式:我们重写了元数据子系统,将分散在不同层级中的元数据合并为一个由 ZippyDB 支持的统一扁平模式。这为以 O(1) 查找将路径解析为存储地址铺平了道路,这是一次阶跃式的改进。
  • 无数据面代理:我们取消了数据面代理,构建了一个胖客户端 SDK,能够直接从存储服务器向客户端流式传输字节。这有助于实现能效目标,也有助于实现更高的吞吐量/更低的延迟。
  • 区域化部署:BLOB 存储栈如今已变得精简,并具备作为区域性或全球性服务部署的灵活性。我们现在在每个 AI 区域中部署与 GPU 同址的区域性 BLOB 存储栈。
图 3:getObject API 的新请求流程。

图 3 展示了 getObject(“/bucket/path”) 的新请求流程。当客户端上的 SDK 收到此 API 调用时,它会向 API 服务器发出 getReadPlan(“/bucket/path”) 请求。API 服务器对每个 chunk 向新的元数据存储执行 O(1) 查找,将路径映射为 (blockId, offset, size) 元组。随后它将 ReadPlanResult 返回给 SDK。SDK 内嵌了 Tectonic BlockClient,因此现在能够直接从 Tectonic 流式传输这些 block 的数据。通过这些改动,我们重建了基础架构,并实现了在 Tectonic 之上增加零开销的目标。通过消除数据代理,我们还控制在了功耗预算之内。

应对流量峰值与热点

在数据和 checkpoint 加载期间,AI 工作负载已知会跨数百个 GPU 并发访问数据。诸如模型权重之类的数据子集往往是“热点”,而 GPU 重启等事件会触发剧烈的流量峰值。在基础架构修复之后,我们的下一个问题是应对这些峰值和热点。幸运的是,BLOB 存储层多年来积累了应对热点的经验,因此我们在此将现有解决方案适配到了 AI 工作负载上。具体而言,我们采用了两种方法:

  • 分布式数据缓存:我们利用 GPU 主机上的空闲内存作为分布式数据缓存,用于存放频繁且并发访问的数据。为实现这一点,我们复用了 Meta 的 Owl 子系统中的组件:我们将 Owl 子系统中的对等节点直接集成到 BLOB 存储客户端 SDK 中,使所有数据访问都经过这一数据缓存。
  • Readplan 元数据缓存:Readplan 指的是从路径到存储地址的映射。我们现在将频繁访问的 BLOB 的 read-plan 缓存在一个类似于 memcache 的分布式内存存储中。

在实践中,我们观察到分布式数据缓存的平均缓存命中率为 80%,而 read-plan 缓存可提供 1-2 ms 的元数据访问速度。本质上,这些简单的机制做了三件事:

  • 吸收峰值流量,并降低对存储的 I/O 需求。
  • 解决元数据热分片的问题。
  • 通过从内存中提供服务,改善 p50 和 p99 延迟。

协议优化

到目前为止我们所讨论的内容让我们完成了 80%。我们通过识别并修复整个技术栈中的瓶颈,实现了剩余的 20%。以下是一些值得注意的问题,但绝非详尽无遗的清单:

  • 落后节点:单个缓慢的存储节点导致尾部延迟。这是一个已被充分理解的问题,我们采用客户端侧的对冲读取来缓解。
  • 出站流量尖峰:在检查点事件期间,客户端通常会产生急剧的出站流量尖峰。这反过来会导致拥塞、超时和重试,最终使 GPU 停滞。我们通过在客户端 SDK 上构建动态并发控制来解决这个问题,根据应用层拥塞信号自动调整并行度。

综合以上所有改进,新的 BLOB 存储栈现在能够在不导致 GPU 停滞的情况下服务 AI 工作负载,在 Tectonic 层之上增加的额外开销可以忽略不计。我们接下来的重点转向了研究。

最大化研究速度

GPU 稀缺且日益地理分布式部署;与此同时,出于性能考虑,训练工作负载需要数据与 GPU 同地部署。这给研究人员带来了一个有趣的挑战:他们现在需要负责跨区域摄取和迁移数据集。

在 Meta,一次典型的训练任务提交涉及以下步骤:

  1. 研究人员从各种来源整理数据,对其进行丰富处理,并将其持久化到 BLOB 存储中。
  2. 研究人员选择他们想要运行任务的区域。
  3. 研究人员提交一个数据摄取作业,该作业会将训练数据集的快照创建到目标区域,并采用针对 GPU 主机内数据加载优化的文件格式。
  4. 随后研究人员等待摄取完成;根据数据集大小,这可能需要数小时。
  5. 研究人员提交训练作业并监控其运行情况。
  6. 研究人员分析输出、调整数据集,并再次迭代,从第 3 步重新开始。

第 2 步到第 4 步可能耗时数小时,并直接影响研究人员的迭代速度。理想情况下,我们希望研究人员的时间花在调优模型上,而不是等待存储。目前,研究人员在启动作业前会复制快照,以便将数据与 GPU 共置,从而实现最优性能。虽然这种性能优化对于持续数周或数月的大规模训练作业来说是合理的,但绝大多数作业要小得多;拥有这些作业的研究人员非常愿意以偶尔的性能下降来换取迭代速度。

因此,我们需要一个系统,让研究人员能够一次写入数据,并在任何地方访问数据,而无需考虑区域边界。我们需要一种工作流,让研究人员能够以分钟而非小时为单位进行迭代。当我们重新回到设计阶段时,这些数据集“一次写入、多次读取”的特性让我们灵光一现。如果我们把存储看作一台行星级计算机中的磁盘,并借鉴操作系统领域的思路呢?当运行在 CPU 核心上的 Linux 进程尝试从磁盘读取文件时,操作系统会透明地按需在缓存的各个层级之间填充数据——内存中的页缓存以及 L2 和 L1 CPU 缓存。这一直觉催生了图 4 中的架构演进:

图 4:数据加载架构演进。

核心思路是将各种主机上和主机外的存储资源用作分层缓存,并以由 HDD 支持的全局 BLOB 存储基础设施作为最终的事实来源。具体而言,我们将 GPU 主机上的内存和闪存用作 L1 和 L2 缓存。同时,我们将由闪存支持的区域性 BLOB 存储基础设施用作 L3 缓存,数据加载器继续通过熟悉的 BLOB 存储 SDK 访问存储。为了有效隐藏延迟并简化数据生命周期,我们依赖以下几点:

  • 数据加载器预取:数据加载器在处理当前批次的同时,将下一批数据集预取到内存中。这种预取会在 BLOB 存储 SDK 层面表现为一次 read 操作。
  • 深度预取:我们在 BLOB 存储 SDK 中暴露了一个显式的 prefetch() API。数据加载器会在后台调用 prefetch() API,从而触发对接下来几分钟内所需数据的显式预取。该 API 会触发将数据从远程存储水合到本地区域的 L3 缓存,并同时预热元数据缓存。
  • 自动数据生命周期:L3 区域解耦闪存层中的数据通常会保留一段配置好的时间,以便在训练周期内跨 epoch 复用。我们支持自定义驱逐策略,包括 TTL 和 LRU 策略。这些驱逐策略还具备容量/配额感知能力。

生产环境一经推出,我们就看到这种新的数据加载范式被迅速采用,而今天我们仍在生产环境中同时支持这两种数据加载范式。为了用数字说明其影响,图 5 展示了推出前后所有工作负载的大致数据摄取时间:

图 5:推出前后的数据摄取时间。

在新型前沿模型每隔几周就发布一次的世界里,这种数据加载范式的转变是一次迫切需要的变革,让我们能够走得更快。

关键要点

现代 AI 工作负载对数据极度渴求,而存储在计算成本和创新速度两方面都扮演着重要角色。存储瓶颈会直接影响 GPU 利用率和计算成本,而在地理分布式 GPU 的环境下,跨区域数据摄取所耗费的时间会直接影响研究的迭代速度。Meta 的 BLOB 存储架构是为服务 Meta 旗下系列应用而构建的,我们需要性能上的阶跃式提升来服务 AI 工作负载。这促使我们重新思考整个架构。通过重建元数据子系统,并采用带有预取/按需水合的分层缓存架构,我们得以有效满足当今工作负载的需求。

未来工作

我们正在持续演进 Meta 的存储,以跟上硬件演进和工作负载需求。该领域的一些未来工作将包括:

  • 将存储扩展至网络极限。
  • 在更高规模下支持检查点保存而不阻塞 GPU。
  • 推理工作负载带来的新挑战,我们正开始着手应对。

来源:Meta Engineering Blog(RSS) · engineering.fb.com