本文作者:王天庆,贝壳计算存储方向容器引擎团队负责人,他专注于云原生技术和AI基础设施的架构设计与实践,在为公司搭建高效、可靠的基础设施的同时,促进了大模型技术在企业内部的快速落地与应用。
导语:随着AI大模型成为技术新热点,众多企业纷纷将AI纳入战略规划。贝壳找房,作为居住服务产业数字化的佼佼者,也增强了AI技术设施的布局。其底层采用的是蚂蚁集团自研的单机分布式一体化数据库OceanBase。那么,数据库在构建AI基础设施时扮演着怎样的核心角色?本文将探讨贝壳找房在 AI 存储底座方面的实践,以此展开深入讨论。
贝壳找房的AI基础设施建设背景
贝壳找房是中国最大的居住服务平台,业务包括二手房交易、新房交易、租赁、家装、家居、家服等,作为居住产业数字化服务平台,贝壳是最早将VR、AI等新技术应用于居住服务的企业,其致力于推进居住服务的产业数字化、智能化进程。
自AI大模型爆火后,贝壳找房很快加大了对AI的投入。目前我们团队有三大模块致力于AI的发展:一是机器学习平台,帮助算法工程师做模型训练和模型推理;二是在机器学习平台下层有两套内部的基础设施提供高性能存储服务;三是内部的云原生基础设施。
在AI基础设施建设的过程中,由于数据的快速增长和对算力的不断调整,存储架构不断演化,在各阶段面临不同的挑战。
分层存储架构演化
贝壳找房AI基础设施建设始于几年前,受AI技术发展态势迅速变化的影响,至今已历经四个阶段的演化。
在非大模型时代,算法工程师训练模型特别简单,只需要一台GPU和一块硬盘,即单机单卡。训练模型逐渐变大,超出了一台机器能够承载的范围。随即便出现了多机多卡的场景,其本质上不会脱离机房,但该场景下无法再使用一块磁盘解决问题,需要网络共享存储。彼时,常用的共享存储开源方案是基于NFS。
2023年大模型的火爆促使模型训练对GPU算力需求及资源使用方式发生巨大变化,我们也从多机多卡单机房结构变成平台化的交付方式,完全云原生化。底层也使用统一文件系统存储千亿规模的文件。
随着算力资源因供不应求导致的稀缺,我们的算力分布在多家公有云的多个地域,包括北京、上海、天津等地,算力的供给多样性给数据集合模型管理带来了更多的技术挑战。
同时,大模型的发展使存储系统存在着两大技术挑战,一类是模型训练过程中的存储瓶颈,随着AI模型的参数量越来越大,文件系统的数据传输能力和Checkpoint的写入效率很容易成为模型训练过程中的性能瓶颈,因此要求存储底座需要具备极高的并发、吞吐的能力。另一类是数据流转的效率。数据集对于大模型工程体系来说,贯穿了整个生命周期。在传统场景中,不同的场景都存在独立的存储介质来满足业务场景,但在大模型的迭代过程中,为了提高GPU资源的使用效率,我们需要尽量减少数据在流转过程中消耗的存储成本和时间成本。
数据流转周期牵涉整个贝壳找房AI工程,从用户端的数据采集到数据处理,再到转化成数据集,最后流转到GPU支撑模型训练。该流程最理想的形式是以文件系统卷的形式挂载。对于整个数据流转来说,无论是数据流入、数据处理、模型训练还是生成模型文件来做模型推理,整个数据的存在形式都是以同一个共享卷的方式存在的话,能极大的减少数据复制带来的时间消耗。
贝壳在此理念的基础上,开发并设计了符合贝壳当下物理环境的分层存储底座来满足数据流转的效率。
分层存储技术选型
分层存储架构分为存储编排和文件系统存储两部分。我们选择了开源的Fluid作为数据编排部分,其具备云原生的数据编排以及缓存加速的能力。
底层的文件存储选用开源分布式文件系统JuiceFS,这是一款面向云原生设计的高性能分布式文件系统,提供POSIX、HDFS和S3协议的接入方式,其高性能特性比较依赖于高性能的元数据引擎和对象存储服务。
目前贝壳内部还存在着一些其他的文件系统,比如CubeFS,为了更好的提高数据流转的效率,我们通过整合多种底层存储并围绕着JuiceFS我们打造了混合云存储底座。
第一层就是接入层,满足各类场景的数据写入/读取的需求,包括云原生场景下、HDFS协议或者直接使用S3协议来对文件进行操作。
第二层是数据编排层,主要是解决跨地域数据流转和数据就近访问的能力。因为数据可能在北京区被生产,但是在上海区被消费,所以需要把数据传输到离算力最近的地方。
第三、四层组成了基于JuiceFS的完整的文件系统底座。JuiceFS依赖元数据和对象存储服务的能力。需要一个高效的元数据引擎和能够满足我们多地域需求的对象存储服务。
然而,元数据引擎的技术选型是非常困难的,如果基于高性能的Redis,存在数据丢失的风险,可能是文件系统的灾难,我们无法容忍。如果是全靠自研,人力投入和时间成本过高,短期内无法落地。综合考虑下,我们确定首要需求是稳定且不丢数据,其次是承载我们数据流转、跨地域的需求。
将OceanBase作为JuiceFS的元数据引擎
在调研了目前市面上的多种元数据引擎存储系统后,我们最终选择将OceanBase作为元数据引擎的技术方案和存储底座。主要原因如下:
1. 对于整个数据流转系统而言,OceanBase可以提供高可用和容灾能力,解决数据流转中跨地域数据同步的问题。
a) OceanBase的每个数据分片都有多个副本,分布在不同的物理节点上,当某个节点出现故障时,系统可以自动切换到其他副本,保证服务的连续性。
b) 通过配置数据副本的存储位置,可实现机架级、机房级、城市级容灾,帮助金融机构应对容灾挑战。
2. 我们有很多机房,算力分散在不同区域,我们需要把数据充分地利用起来,就需要元数据能够在各区域飘来飘去,在离算力最近的地方读到元数据可以保证文件系统的读取效率。OceanBase的多活能力可以解决这个问题。
3. 我们是云原生和AI基础设施建设的团队,不太擅长数据库运维,上文也提到数据流转涉及整个企业的多个业务模块,因此我们需要存储底座具备资源隔离能力和较高的可运维、可管理能力。OceanBase提供了强大的运维管理平台OCP对数据库进行7*24小时监控,安全可靠。
4. OceanBase的原生多租户架构和租户级资源隔离能力,可以满足我们的需求。同时,其性能均衡,能支持百亿到千亿量级数据。
举个例子,下图是京津区算力中心和上海区算力中心的元数据传输的架构解决方案。可以看到整体的算力资源分为IDC和公有云,且拥有多家公有云供应商。我们在IDC内尤其是同区的机房内,使用OceanBase多zone的能力,通过OBProxy分别转化到不同的副本中。针对跨云甚至跨区的场景,以腾讯云为例,我们巧妙借助了腾讯云MySQL的能力,当 IDC的数据飘在上海时,先把数据基于OMS同步到京津区腾讯云的数据库,再通过云上的DTS工具同步到上海区的数据库,由上海区的数据库提供元数据的处理能力。
为什么出现这么复杂的架构,而非利用OceanBase在上海区整体做同步?
这是出于物理限制,我们测试过一些场景,如果让OceanBase在上海区同步数据,受限于云联网和带宽会出现极高的同步延迟。而目前的方案可以保证最低的数据延迟,我们只需解决数据流转在2w TPS时从京津区写入上海区在秒级内完成,这个速度在整体数据生产过程中可以满足大部分业务场景需求。另外,IDC和其他算力中心基本都在OceanBase的多zone管理模式下,数据流转速度更快。
OceanBase作为JuiceFS的元数据引擎,在同机房访问文件系统场景下,表现也很出色。在单客户端场景下,文件规模在2000万左右时,Oceanbase的响应时间可以控制在1~2ms之间,只有在一些大量list删除时才会偶有抖动,耗时基本能控制在2~10ms之间。
将OceanBase作为对象存储服务的元数据引擎
贝壳找房内部自研了一套对象存储服务,作为JuiceFS的数据持久化层。由于我们存在跨区读取数据的场景,比如对象存储数据存储在北京区,但是需要从上海区读取,甚至我们还面临着跨公有云的情况。
因此,我们希望对象存储服务具备跨区甚至是跨云数据复制的能力,可以把一份数据同步到不同公有云的不同地区,离算力更近一些。为此我们自研了一套对象存储系统KOS来满足我们的需求。该系统本质上并不提供真实的存储能力,而是一层S3协议代理层,最终数据都在落在公有云的对象存储上,比如腾讯云COS上。我们的对象存储系统只解决一个问题——访问加速。对象存储系统的部署形式是在京津区和上海区部署我们KOS服务,通过跨区复制能力,保证上海区、京津区之间KOS文件复制的实时同步。
对象存储本身也是有元数据的,在海量数据的场景下,对象存储元数据访问的性能也会极大的影响对象存储的整体性能,尤其是在文件系统这类需要频繁查询文件元信息的情况下。因此,我们使用OceanBase作为KOS的元数据的底座,以推动整个对象存储服务加速。如下图所示,对象存储系统分三个组件,
- KOS-Proxy 协议代理层:主要用于实现S3接口协议,该组件是完全无状态服务,元数据主要从KOS控制面中获取。
- KOS-Cache 数据缓存层:主要功能是从底层真实的对象存储中缓存数据到本地磁盘中,并且可以分布式部署形成缓存集群来提高对象存储的吞吐能力。
- KOS-Meta元数据层:主要对对象存储服务提供元数据能力,以OceanBase为底层元数据引擎,提供就近获取到对象存储元数据信息的能力。
在这个流程中,对于文件的读取,会优先判断文件是否启用了数据缓存,如果存在缓存的话会优先从缓存节点KOS-Cache读取数据,否则降级到远端的对象存储读取。为了保证数据一致性,所有归属于同一组的缓存节点都会以哈希环的形式分布好,每个cache服务通过etcd对外分享自己在环中持有的Token信息和位置信息。数据的读写都会通过一致性hash算法写入到指定节点,保证数据的一致性。最终元数据加速的原理是通过S3协议在对象存储文件生命周期过程中,生成文件对应的元信息并写入OceanBase中,同时OceanBase做好多AZ和多地域的同步支持,此时就可以通过OceanBase实现支持海量数据的对象存储服务。
拥有对象存储能力后,我们访问云上的对象存储都会转化为本地机房访问的对象存储,实现了加速。访问文件系统时非常高效。下图展示了本地访问与云上访问的性能对比数据。
从图中可见,对于大量小文件加速效果比较明显,强依赖OceanBase提供的强大性能。在跨机房场景下,性能提升比较明显,有效提升读场景下的吞吐上限。不过,该方案对于对象存储的写场景提升效果不明显。
对象存储服务优化后,我们考虑怎么把JuiceFS用起来。在用户侧,数据要先在京津区计算后再拷贝到上海区,然后从上海区拉取数据进行训练。这个流程中要么存在带宽小、专线贵的问题,要么会遇到部分小文件场景难以优化吞吐导致延迟较高的问题。
一种优化思路是做镜像文件系统。首先用户在京津区创建一个普通卷,该卷的自动接入会连接到京津区的元数据引擎和对象存储服务。然后用户在上海区创建一个京津区卷的镜像卷,用户使用该卷的时候,自动接入会自动识别并接入到上海区的元数据引擎和对象存储服务。该思路减少了数据流转的时间,从传统的数据生产到数据清洗、数据复制、训练,到优化为数据生产、进行数据清洗、再训练,可以降低数据复制的时间成本。数据量较小时可秒级完成。对于不需要所有的数据都多地区多写的情况,还可以通过镜像文件系统的能力,进行跨地区预热,将数据同步到其他地区,JuiceFS的文件块大小对于公有云对象存储的数据同步比较友好,同步效率会更高。进而还能帮助省钱,因为在AI领域有一个共识——GPU很贵,闲着就是烧钱,所以一定要保证数据同步效率跟得上算力的速度。
OceanBase应用场景探索
除了将OceanBase作为AI基础设施的存储底座外,我们在其他的场景中,也对OceanBase的应用进行了探索。
场景一:可观测性。
在维护数千台服务器和KOS集群时,我们面临的最大挑战是系统的可观测性。传统的可观测性系统,如日志系统Loki、Prometheus等无时无刻都在采集各个系统的日志、指标数据,这些数据庞大繁杂其缺乏实时分析的能力,对运维人员而言是一种困扰,当遇到故障需要快速定位分析的时候,往往无法快速的检索出重要的指标数据。所以我们基于云原生标准,结合OceanBase的能力补齐了可观测的领域实时分析的能力。
这套系统的核心是将可观测数据经过过滤、分组、提取、转化及路由,汇聚到不同的存储系统中,对于海量偏归档类数据,我们会写入到比较廉价的存储系统中,比如对象存储。对于使用频率高以及重要巡检的可观测数据时,经过数据清洗后日志和指标数据会流入OceanBase以借助实时分析的能力能够更快速的定位异常。以域名类场景为例,当出现报警时,我们会面临额外的风险,比如外部攻击、爬虫等,我们需要尽快排查风险的IP来源,以及每一个IP的增长趋势。OceanBase的实时分析能力能够帮助我们快速定位异常,增加报警解决的效率。
场景二:探索OBKV作为元数据引擎。
最后简单分享一下,也算是贝壳后续对OB的探索,这个比较简单,因为这个也是最近开始尝试,基于OBKV在文件系统层面的尝试,我们内部现在只是做了第一版的基于OBKV的元数据引擎的实践,整体从SQL引擎切到OBKV上,因为文件元数据结构相对简单,对应的表结构也比较简单,本质上并不需要SQL的形式,KV的方式就能满足我们全部功能需求,并且抛开掉SQL解析的时间消耗,也能够提升元数据引擎的整体性能,所以我们做了一些尝试和探索。
近期我们针对该探索进行压测发现整体效果非常理想,OBKV 场景下,百万级的文件读写的响应时间提升2~4倍,原来的2~10ms变为1ms甚至更低,偶尔在抖动情况下也会稳定在5ms左右。OBKV少一层SQL解析,理论性能更高。另外,由于OceanBase具备多模KV能力,支持HBase和Redis协议,且拥有丰富的工具体系,我们可以直接复用OceanBase的运维能力。
场景三:引入 ob-operator 提高集群快速交付能力。
在贝壳我们也在尝试引入和使用 ob-operator。因为我们团队是容器团队,有相对完善的本地盘的存储方案以及完善的容器基础设施,很多基础组件运维过程中存在着大量的数据库需求,所以通过operator的方式按需做集群交付可以最大程度复用我们的容器基础设施,一定程度上也能够实现OceanBase集群的快速交付,相对裸金属的形式更具有灵活性。
以上就是贝壳找房AI方向对OceanBase的应用与经验,后续我们将持续探索OceanBase的其他能力,欢迎留言交流。