掘金 后端 ( ) • 2024-06-12 16:50

贝壳机器学习平台的计算资源,尤其是 GPU,主要依赖公有云服务,并分布在不同的地理区域。为了让存储可以灵活地跟随计算资源,存储系统需具备高度的灵活性,支持跨区域的数据访问和迁移,同时确保计算任务的连续性和高效性;此外,随着数据量的增长,元数据管理的压力也在逐渐加大。

贝壳机器学习平台团队从去年开始对存储系统进行重构,选择了基于 JuiceFS 的存储方案。目前 JuiceFS 作为存储底座服务于整个机器学习平台,不仅提高了对混合多云架构的适应性,还大幅提升了数据处理效率。

该存储平台已支持多个场景,例如,**模型加载时间从超过 10 分钟缩短至 30 秒以内,提升 20 多倍,大幅提高了资源利用效率。此外,贝壳团队基于 JuiceFS 研发了多 AZ 分布式缓存以及镜像功能。本文将详细介绍贝壳在此重构过程中的演进历程和具体实践。

01 贝壳 AI 基础设施演化

最初的机器学习过程非常简单。在贝壳早期,机器学习只需要一台 GPU 机器,挂载一块本地硬盘,然后进行调优即可。随着工程自动化程度的要求变高和规模的不断扩大,这种原始的“裸金属”方式无法承载算力调度的效率。因此,逐渐出现了面向单机房或单集群的架构,以满足自动化发展的需求。在这个阶段,引入了 Kubernetes 集群和 NAS 共享存储,挂载到机器后完成训练任务。

随着大型模型的出现,模型规模急剧增大,对算力的需求随之增加。在当前中国的特殊市场环境下,获取算力资源变得更加困难,公有云已成为主要的算力来源。在公有云平台上协调 GPU 资源时,用户可能会面临地域限制的挑战,这一变化促使包括贝壳在内的企业对 AI 基础设施架构进行调整。

贝壳 AI 基础设施演化:单机-多机多卡-平台化-混合云

目前,我们团队负责的两个平台,混合云 KCS 容器服务和 AIStudio 机器学习平台,均基于容器技术并构建在大型混合云平台上。容器平台依赖于自建 IDC,覆盖多个机房,并整合各种公有云服务,涵盖北京、上海等多个地区。贝壳的基础设施规模经历了从裸机交付到单 Kubernetes 集群交付,再到多集群、多机房交付的演变,直至联邦制交付模式,实现了跨地域的资源管理。

演化趋势

在平台演化过程中,基础设施层呈现出如下这些变化:

算力和存力分散:以实际场景为例,当数据位于北京而训练任务需要在上海进行时,直接挂载北京的数据卷将因网络延迟导致训练效率低下。因此,如何缩短计算和存储之间的距离,提高数据访问效率,成为了基础设施架构优化的关键。

存储跟着算力跑:在算力资源紧张的背景下,我们不得不考虑如何让存储更接近计算能力。由于 GPU 资源的获取变得困难,传统的“算力跟着存储跑”的策略可能需要转变为“存储跟着算力跑”。这要求我们根据计算任务的实际地理位置灵活配置存储资源,确保两者之间的高效协同。

跨地域数据管理难题:我们面临的存储与算力之间的远距离问题。为了缩短这一距离,最直接但效率极低的方式是数据拷贝。即将数据从一处转移到另一处,尤其是当需要跨越较大距离,如从北京到上海时,其效率问题尤为突出。以我们最近的一次数据迁移为例,涉及 20 TB的数据迁移需要耗时 11 天,主要是因为涉及大量大小文件的处理,对于当前依赖高效数据处理,尤其是 AI 训练的业务来说,这样的效率是无法接受的。

存算分离:鉴于单盘存储容量的上限,我们需要采用存储与计算分离的架构来确保整体存储容量的充足性。这种架构不仅能够应对存储容量需求的增长,还能够提高系统的灵活性和可扩展性。

文件系统架构的演变:文件系统的发展已成为一个关键挑战,从传统的本地磁盘到如 Network File System的共享存储系统,再到贝壳采用的开源多节点文件系统。这些变化推动了数据存储方式的革新,也引入了新的问题。

02 存储方案探索:CubeFS & JuiceFS

鉴于基础设施的发展趋势及贝壳内部的具体需求,我们需要确保存储层能够应对以下挑战:

  • 支持多地域混合云架构:存储解决方案必须支持多地域混合云架构,以满足不同地域的数据存储需求;

  • 百亿到千亿级别小文件存储能力:目前,贝壳的文件系统数据量已达到 14PB,文件总数近 50亿。随着 AI 的快速发展,大量历史数据被清洗并转化为可训练数据和结构化数据。我们目前每周的数据增长量已占到总文件数的十分之一,即每周新增近 5亿个小文件。预计这种趋势将在今年持续,给我们的存储系统带来严峻挑战。因此,我们的系统需要能够支持从百亿到千亿级别的小文件存储;

  • 存储性能:面对广泛分布的文件存储需求,尤其是在 AI 应用中对性能的极高要求,如何提升存储系统性能,以满足不断增长的数据存储和访问需求,成为我们当前必须解决的问题;

  • 低成本与低维护:我们追求降低成本和维护需求,尽量减少对第三方组件的依赖,确保在提升性能的同时,控制成本在可接受的范围内。

针对贝壳的特定场景,我们深入研究了 CubeFS 与 JuiceFS 并将他们应用于不同场景。模型训练场景对 I/O 吞吐和 IOPS 要求极高,我们在 IDC 内部主要采用 CubeFS 全闪存储集群来构建文件系统,目前 CubeFS 在贝壳内部已具备一定应用规模。

对于跨机房、地区或者地域的复杂数据处理场景我们选择了使用 JuiceFS。例如,在进行模型训练时,通常需要先处理原始数据,执行数据清洗任务,随后再生成中间数据或者训练数据。此外,这些数据还需在多个地点之间进行迁移。贝壳基于 JuiceFS 的灵活架构设计了支持跨地域、混合云架构的文件系统来应对贝壳AI基础设施的快速发展。

JuiceFS 依托于公有云对象存储,不仅成本低廉,还能提供几乎无限的存储容量,最大限度地发挥云存储的优势;其性能主要依赖于对象存储和元数据引擎。元数据引擎的选型能满足各种场景,特别是处理大量小文件的能力。JuiceFS 成功解决了我们在非单机房模型训练场景中遇到的问题,如数据集清洗、同步以及容量限制等,有效填补了贝壳生态中对跨机房、高扩展性文件系统的空缺

03 基于 JuiceFS 的存储底座设计

元数据引擎架构设计

JuiceFS 采用的是元数据和数据分离的架构。对于元数据引擎的选型,我们考虑了三个方案。

  • 第一,Redis 以高性能闻名,但由于我们对数据丢失的零容忍态度,特别是在存储大量训练数据的场景中,我们很快排除了使用 Redis 的方案。此外,考虑到需要支持大量文件和实现跨机房同步的挑战,Redis 集群的规模及其同步功能的局限性,也是我们决定放弃使用它的主要原因;

  • 第二,具有同步能力的 TiKV 和 OceanBase ;

  • 第三,自研元数据引擎。

最终我们选择了 TiKV 和 OceanBase,主要基于以下几个原因:

  • 稳定性:对于贝壳的当前状况而言,稳定性是至关重要的。TIKV 和 OceanBase 这两支团队在开源社区中拥有非常成熟的运维体系,特别是在实现跨地域数据同步方面,它们提供了非常成熟的解决方案。相比之下,如果我们完全自主研发,不仅研发周期会很长,而且可能不利于我们整体项目的快速落地,特别是在 AI 领域快速发展的背景下。

  • 性能:我们也对这两种元数据引擎进行了性能测试。结果显示,在性能层面上,它们的差异并不大。

  • 其他因素:在大多数场景中,I/O 性能受限是一个常见问题。元数据可能只是其中的一部分原因,还可能受到专线带宽、对象存储等其他因素的影响。综合考虑这些因素,我们最终选择了 OceanBase 作为最终的元数据引擎。

贝壳元数据引擎架构 

该架构的核心在于充分利用公有云资源,以贝壳北京区域的 OceanBase 集群为例。在北京,我们设有专门用于 AI 计算的机房和负责其他服务的主机房。面对支持 OceanBase 在上海的同步需求时,高昂的专线费用和同步工具的效率及延迟问题成为挑战。

经过多方权衡,我们选择了一个既经济又高效的策略:利用腾讯云作为主要的公有云提供商,通过其云内网同步能力实现北京到上海的数据同步。具体操作中,我们采用腾讯云的 MySQL服务及其内网同步机制,有效解决了跨区域同步的延迟,实现了每秒约 2 万条记录的写入性能,延迟保持在秒级

在贝壳的元数据引擎架构中,写入操作需首先在北京的主力机房进行,随后系统将数据分发至各机房,确保 了元数据的一致性和实时性。这一策略有效提升了数据处理和分发的效率,为业务提供稳定可靠的支持。

多 AZ 分布式缓存加速

在使用 JuiceFS 的过程中,我们面临的主要任务是同步元数据及对象存储中的实际数据。JuiceFS 企业版可提供分布式缓存方案,我们目前使用的是社区版,它在异地同步及数据加速方面有一定限制。因此,为了快速从北京到上海的数据同步需求,我们自主研发了一套分布式缓存加速系统。

该系统本质上是一个对象存储代理系统,协议层是自研的,持久化层完全依赖于云服务提供商提供的对象存储服务。我们通过构建一系列的缓存加速能力,使访问云对象存储的性能与访问基于本地 NVMe 构建的对象存储服务(如 MinIO)的性能相当,同时该系统支持多写复制,当把数据写入北京区域时,可以同时向上海或其他区域进行同步写入,再结合 JuiceFS 的单机缓存加速功能,进一步提高了数据访问速度。

架构设计

该分布式缓存加速系统采用了与 JuiceFS gateway 类似的设计,建立了一个 S3 网关,负责数据分发和同步复制任务。虽然数据同步并非实时,对于大文件的同步通常延迟控制在分钟级。然而,得益于 JuiceFS 文件分块特性和我们的缓存策略,我们能够实现几乎即时的数据同步,一旦数据写入北京区域,它几乎可以立即被同步到上海或其他区域。

贝壳多 AZ 分布式缓存加速架构

我们的分布式缓存系统主要包括两个核心组件:kos-proxy 和 kos-cache。kos-proxy 作为 S3 协议的代理,提供鉴权、控制面等功能,类似于 MinIO Gateway 这样的无状态服务。而 kos-cache 则负责存储分发出去的对象存储文件,其缓存维度基于 bucket+文件对象。当对象过大时,系统会自动拆分成多个文件块进行存储。以 k8s 集群为例,我们可以在每个节点上部署 kos-cache,以确保对象存储的数据能够分散在多个缓存节点中,从而在当前机房实现最快的访问速度。在最佳情况下,我们甚至可以直接从本地缓存中获取所需数据,极大地提升了访问效率和响应速度。

原理:分布式哈希技术

关于分布式缓存的基本原理,其核心是运用了分布式哈希技术。在系统架构中,无论是作为代理服务的 kos-proxy 还是作为缓存节点的 kos-cache,都是架构的关键组成部分。核心区别在于缓存数据的共享策略:如果缓存节点设置为共享数据,它们就直接作为数据的存取点;如果设置为不共享,这些节点则充当数据的转发代理。目前,我们支持三种接入方式:

  • 第一种是网关形式,通过配置域名对外提供服务;

  • 第二种是 side-car 方式,特别适用于 k8s 环境,通过向容器注入代理服务,使得访问 S3 存储如同访问本地存储一般便捷;

  • 第三种方式是 SDK 对接,我们与 JuiceFS 进行了深度整合,实现了基于 JuiceFS 的 kos 后端存储,无需额外配置 proxy 组件,数据即可直接写入远端存储。

一致性原理

分布式对象存储系统支持跨区域的访问控制(ACL),所有 kos-cache 节点共享一个统一的控制面。这一控制面类似于一个庞大的联邦系统,无论在北京还是上海,都能通过它进行统一的管理和调度。每个节点都持有部分虚拟的存储单元,这些单元通过哈希算法进行分配和管理。

在实际应用中,我们采用了 128 个 token 值进行哈希计算。哈希策略主要基于两个维度:一是根据 bucket +文件 key 的信息查找对应的虚拟节点;二是结合 region 和 zone 信息,根据复制因子和 zone 配置,将数据写入到指定的区域。例如,如果设置了两个复制因子,并且目标区域仅包括北京和上海,系统会首先选择北京区域进行写入,然后在确保 zone 不同的前提下,将数据同步到上海区域。这种设计确保了数据在写入时能够同时分发到不同的地区,有效解决了跨地区访问的问题。

性能提升

在存储性能提升方面,由于当前硬件设施的局限性,我们主要通过优化数据同步机制来提高存储效率,确保数据能够更快速地完成跨地区同步。

首先,我们所进行的分布式缓存加速测试,虽能作为参考,但并不具备实际跨地区部署的代表性。这是因为测试环境仅限于 IDC 内部,即北京区内的测试,并未涵盖跨地区的实际部署场景。跨地区的性能差异显著,通常表现为几十兆至几百兆的带宽下降,直至基地级别的差异,这使得当前的测试结果在跨地区部署中缺乏参考意义。

缓存系统性能对比:内网带缓存 vs 内网不带缓存

然而,在与腾讯云的跨云访问测试中,相较于本地 IDC 的访问性能,我们的分布式缓存加速方案实现了大约 25% 的性能提升。

这一提升虽显著,但系统仍存在瓶颈。特别是在处理大量小文件时,系统的性能衰减尤为严重。这一问题的根源在于我们的系统目前尚未集成元数据系统,而是依赖于本地磁盘进行元数据存储。此外,由于我们广泛采用 S3 协议,公司内许多依赖于 S3 协议的组件,如可观测性工具(如 Prometheus),都基于该分布式缓存加速系统。在实际应用中,我们已成功通过该系统提升了查询性能,例如,现在能够轻松查询 30 天甚至 60 天的数据,而之前即使查询 14 天的数据也会遇到性能瓶颈。

综上所述,尽管我们的分布式缓存加速系统在本地 IDC 内表现出色,但在跨地区部署中仍需进一步优化。同时,我们也在积极探索元数据系统的集成方案,以进一步提升系统性能,满足各类应用场景的需求。

镜像文件系统

当进行跨区数据复制时,用户首先在北京区创建一个数据集(JuiceFS 卷),这个数据集本质上是一个可在北京区挂载的 JuiceFS 卷,其底层将自动完成卷的初始化。随后,用户需要执行第二步操作,即在上海区创建一个镜像文件系统,并确保该文件系统与北京区的卷进行关联。

我们的系统会自动完成所有必要的配置,使得用户只需在北京区写入数据,系统便会自动将数据同步至上海区。此外,镜像文件系统的配置是灵活的,用户可以根据需要配置多个镜像位置,如北京、天津或其他地区。

然而,在实际应用中,我们遇到了一个重要的挑战。镜像文件系统必须设置为只读模式,这不仅仅是在 JuiceFS 层面,还需要在元数据权限分配和 S3 权限分配等方面也进行相应设置。这样的设置可以确保数据的安全性,避免在意外情况下发生写操作,从而导致同步机制出现不可控的场景。

因此,我们决定将这一过程产品化,主要是为了避免交互过程中出现的不可控因素,尤其是防止数据在两地同时写入而产生的双写问题。通过这种产品化的解决方案,我们能够向用户提供更稳定、可靠的数据同步服务。

目前,我们正在积极推广这个内部文件系统产品平台,其核心功能之一是实现两个文件系统之间的数据同步。虽然这些功能虽然处于技术的底层,但却是非常关键的。这种同步功能不仅在技术层面高效,还能开启多种创新的应用场景,为用户带来实际与潜在的价值。

该文件系统平台优化的首个方面是数据同步的即时性。它允许数据同步从数据写入阶段便开始进行,这与传统的 AI 工作流程形成鲜明对比。在传统流程中,数据生产、清洗、复制和训练等步骤耗时较长,特别是在数据复制环节,由于基建能力的不足(如带宽较小等因素),效率往往低下,进而影响整个工程效率。我们的文件系统通过优化链路,从数据生产到数据清洗,有效减少了数据复制的时间,使数据能够更快地进入训练阶段。

其次,基于该文件系统的能力,我们进一步实现了数据预热的场景。当数据集庞大且用户不需要所有数据都进行两端同步时,可以选择性地针对清洗后的数据或定向型数据进行预热处理。这一功能有助于用户将数据从一个区域快速分布到另一个区域,以加速特定任务(如训练)的执行。

总的来说,我们开发这一内部文件系统产品平台提高了整个基础设施的工程效率,减少了数据复制时间,帮助用户能够高效地完成各类任务。

04 JuiceFS 的工程实践与案例分析

AI 模型仓库

随着大模型时代的来临,模型的大小不断增大,我们目前处理的最大模型已超过 130GB。在此,我们聚焦一个简单的场景:模型训练完成后的推理阶段。在这个阶段,需要部署大量的服务,类似于微服务架构,可能需要开启超过 100 个副本来运行推理任务。对于如此庞大的模型,如果直接分发到开发集群中,将面临严峻的挑战。以 S3 作为模型仓库为例,如果一次性拉取大模型到多个副本,将会对带宽造成巨大压力,甚至可能导致 S3 服务崩溃,进而影响到其他在线业务。因此,大模型导致的高带宽占用成为我们迫切需要解决的问题。为此,我们采取了三个原则来优化模型管理和分发过程。

  • **首先,力求避免物理复制,即避免直接从中心仓库拉取大模型到所有副本。**相反,我们考虑先在机房内部进行模型的分发,以减少对外部带宽的依赖,但这种方法可能带来较长的分发周期。

  • 其次,避免中心化设计。传统的中心化存储在处理大模型时容易受到带宽限制。因此,我们寻求更分布式的解决方案,以减少对中心存储的依赖。

  • 最后,充分利用公司内部已有的技术能力进行复用。贝壳在机器学习平台建设方面起步较早,因此我们可以利用这些成熟的技术和框架来优化模型管理和分发。例如,我们已经成功将 JuiceFS 等技术应用于模型存储和管理中,进一步提升了系统的效率和稳定性。

贝壳模型仓库-方案设计

我们基于 JuiceFS 的架构设计了一套 AI 模型仓库方案。该方案的核心思想包括以下几个部分:

模型部署和管理:我们提供了基于 JuiceFS 卷和模型服务控制面的原理。此外,还配套了一个模型仓库的命令行工具,类似于Docker,用户可以通过这个工具进行模型的部署和管理。

模型服务控制:我们主要关注于鉴权、元数据等一系列管理功能。而模型本身则存储在 JuiceFS 卷中。鉴于模型与镜像的相似性,它们都需要标签(Tag)来标识版本。因此,我们利用 JuiceFS 的网络能力,通过元数据的复制而非底层数据的真实复制,实现了模型版本管理。

模型的拉取:我们提供了两种模型部署方式。第一种是在 Kubernetes 环境中,直接将 JuiceFS 卷挂载到 Pod,利用 PV 和 PVC 自动将模型文件挂载进去,这适用于数据密集型场景。

第二种方式是远程拉取,例如直接在物理机上操作,我们提供了一种方法将模型直接拉取到本地并启动。对于远程拉取,我们利用元数据和镜像文件系统的加速技术,使下载过程既高效又完整,相当于在内网中进行下载。此外,由于我们在机房内进行了缓存加速,这种方式几乎不会对带宽造成影响,与传统的直接从对象存储中拉取模型形成鲜明对比。

模型耗时对比

05 未来展望与技术创新

首先,我要强调我们当前面临的一项紧迫且务实的挑战:针对 JuiceFS 打造具备企业级控制面能力。JuiceFS 在使用过程中展现出的技术灵活性,虽然带来了诸多便利,但同时也引入了不可控因素,尤其是在大规模部署时,一旦出现问题,其排查难度显著增加。

为了解决这一问题,我们计划引入一系列规则与限流机制,以应对可能出现的资源过度消耗情况,如同时启动多个客户端写入同一 JuiceFS 卷等场景。这不仅需要增强对 JuiceFS 的控制能力,也是我们未来发展的重要方向之一。

具体而言,我们将从三个维度着手:

  • 提升运维效率:通过社区版支持的平滑升级等方式,确保 JuiceFS 在企业内部的使用更加高效;

  • 增强可观测性:这不仅仅局限于 JuiceFS 本身的监控,而是整个体系架构的可观测能力;

  • 强化管理功能:包括动态限流规则的下发和配置的动态调整等。

此外,在解决 AI 问题时,我们观察到了一个显著的趋势,即数据生产方式的变革。当前,大量数据被直接存储在各种文件系统中,如 CubeFS 和 JuiceFS,而上层的数据处理方案尚未形成统一标准。例如,多模态数据的融合、数据向文件系统的直接写入以及基于向量化数据探索的 Region 等技术的兴起,都反映了这一趋势。

为了应对这一变革,我们提出了一个务虚的设想,即如何借助 AI 的能力来提升文件系统的数据处理能力,实现数据处理与 AI 的一体化。在近期的工作中,我们已明确将解决存储性能问题作为重点,特别是在与 RDMA 技术的整合方面,以期通过社区的共同努力,推动这一探索的深入发展。