基于 JuiceFS 构建高校 AI 存储方案:高并发、系统稳定、运维简单

中山大学的 iSEE 实验室(Intelligence Science and System) Lab)在进行深度学习任务时,需要处理大量小文件读取。在高并发读写场景下,原先使用的 NFS 性能较低,常在高峰期导致数据节点卡死。此外,NFS 系统的单点故障问题也导致一旦数据节点宕机,该机器上的数据将完全不可用。扩容问题同样棘手,每增加一台数据节点,就需要在所有计算节点上进行多次挂载。而新增的数据节点由于数据量较小,并不能有效分担读写压力。

为解决这些问题,经过初步评估,实验室选择了JuiceFS 作为替代的存储方案。当前,结合TiKV 的 JuiceFS 已成功管理超过 5 亿个文件。新方案显著提升了在高并发场景下的性能和系统稳定性,确保了深度学习训练过程中计算节点的连续运行,同时基本解决了单点故障的问题。

此外,JuiceFS 的操作简便易学,甚至不需要专职的存储管理人员来维护,这对于主要由 AI 领域学生组成的实验室集群管理团队来说,极大减轻了他们的运维负担。本文将详细介绍新方案的选型与实践历程。

01 深度学习场景存储需求

实验室集群主要用于深度学习的训练和方法验证。在训练过程中,我们面临四种主要的读写需求。

  1. 训练过程中需要读取大量的数据集文件。

  2. 在模型训练的初始阶段,我们需要加载一个 Conda 的环境,这涉及读取众多不同大小的库文件。

  3. 在训练过程中,随着模型参数的调整,我们需要频繁地写入不同大小的模型参数切换文件,这些文件的大小可能从几十兆字节到数几字节不等,具体取决于模型的大小。

  4. 我们还需要记录(每次训练的)训练日志,这主要涉及到少量数据的频繁写入。

基于上述需求,我们对存储系统有以下四个主要期望:

  • **首要的是,系统在高并发的读写环境下应具备出色的稳定性。**在确保稳定性的基础上,我们再追求性能的提升。

  • 其次,我们希望系统能够消除单点故障,即任何节点的故障都不应影响整个集群的训练进程。

  • 第三,我们期望系统具有友好的运维特性。考虑到我们实验室团队成员主要专注于 AI 深度学习,对存储系统的专业知识了解有限,因此我们需要一个运维简便、维护频率较低的存储系统。

  • 最后,我们希望系统能够提供一个 POSIX 接口。由于我们使用 PyTorch 框架进行模型训练,如果系统支持 POSIX 接口,将极大地降低用户的学习成本,同时减少对现有代码的改动。

实验室现有的硬件配置

首先,我们的硬件系统主要包括三类设备。

第一类是数据节点,我们目前拥有大约三四台这样的数据节点。这些节点主要由大量机械硬盘构成,每个节点的机械硬盘都搭建RAID6阵列,所有节点加起来的总存储容量近 700TB。

第二类是我们的计算节点,这些节点主要搭载了 GPU,用于处理计算密集型任务。在存储方面,由于 JuiceFS 具有缓存功能,我们为这些节点配备了 1 至 3 个 SSD 缓存盘,每个盘的大小约为 800GB。尽管这些缓存盘的大小看起来并不庞大,但它们通常能够缓存多个完整的数据集,前提是数据集的大小适中。

第三类是基于我们使用 TiKV 作为元数据引擎的考量,我们配置了三个 TiKV 节点,专门用于作为元数据引擎运行。这些节点的数据盘容量大约为 2TB,内存则主要配置了 512GB。根据目前的使用情况,当处理大约 5 至 6 亿的文件量时,每台节点大约使用了 300 多 GB 的内存。

NFS 的存储解决方案所面临的挑战

在初期,当计算节点数量较少时,我们采用了在数据节点上构建单机文件系统的策略,并通过简单的 NFS 挂载方式,将这些文件系统挂载到各个计算节点的目录上。这样,当需要添加第二台数据节点时,我们只需将其挂载到新的目录上,即可实现数据在所有节点间的共享。此方案在运维上相对简单,但随着节点数量的增加,我们逐渐发现基于 NFS 的存储系统性能显著下降。

在高并发训练高峰期,系统常出现明显的卡顿甚至卡死现象,这极大地影响了我们的工作效率。为了缓解这一问题,我们曾尝试将集群划分为两个小集群,以减少每个节点的数据压力。然而,这一临时措施并未带来显著的改进,反而带来了新的问题,如不同集群间数据的互通性受限。

总的来说,我们在处理大量小文件读取的场景下,原有的 NFS 存储方案表现出了较低的读取性能和较高的宕机风险。此外,整个系统缺乏缓存机制,而深度学习数据集在训练过程中需要频繁读取,这无疑增加了读写压力。因此,我们需要寻找一种更为高效、稳定的存储解决方案,以应对这些挑战。

02 为何选择 JuiceFS

以下是我们选择 JuiceFS 的主要原因:

  • JuiceFS 支持 POSIX 接口,这意味着在迁移系统时,用户几乎不会感受到任何影响,实现了无感的迁移体验。

  • JuiceFS 的缓存功能对于深度学习模型的训练尤为重要。尽管在首轮数据加载时可能无法直接命中缓存,但随着训练的进行,后续轮次几乎能够百分之百地利用缓存,从而显著提升训练过程中的数据读取速度。

  • JuiceFS 的回收站功能为用户提供了数据恢复的可能性,我们设置的为期一天的回收站使得误删的文件在一天内得以恢复,这在实际应用中已帮助用户及时恢复了误删的数据。

  • JuiceFS 还配备了一系列特有的文件管理命令,这些命令不仅方便用户使用,而且相较于传统文件系统,其功能更为快速和高效。

  • 值得一提的是,在运维层面,JuiceFS 的表现格外出色。由于我们实验室没有专职的人员负责存储,我们期望的存储系统应具备简单性和低运维频率的特点,而 JuiceFS 恰好满足了这些需求。它提供了丰富的文档资源,使得我们在上手和解决问题时能够迅速找到解决方案。JuiceFS 能够自动备份元数据,为数据提供了额外的保护层,增强了我们的安全感。JuiceFS 自带的 Prometheus 和 Grafana 监控功能使得我们能够方便地在网页端查看整个系统的状态,包括文件数量的增长情况、文件使用量以及整个系统的大小等关键信息,这为我们提供了及时的系统监控和管理的便利。

03 搭建基于 JuiceFS 的存储系统

首先,我们的 JuiceFS 采用了 TiKV 作为元数据引擎,同时利用 SeaweedFS 作为对象存储。

总体来看,JuiceFS 分为两个目录进行挂载。第一个目录用于存储用户文件,采用独立挂载的方式使我们能够灵活调整挂载参数,以满足不同目录的特定需求。在用户文件目录方面,我们主要沿用了默认的挂载参数,以确保稳定性和兼容性。

第二个在数据集目录方面,鉴于其几乎只读的特性,我们特别增加了元数据缓存的失效时间。这样做可以在多次读取过程中多次命中元数据缓存,从而避免重复访问原始数据,显著提升数据访问的速度。正是基于这一改动,我们选择了将数据集和用户文件分别挂载于两个不同的目录。

此外,我们还进行了一项实践上的优化。考虑到计算节点的主要任务是处理计算任务而非后台任务,我们在一台相对空闲的节点上配备了较大的内存,专门用于处理后台任务,如备份元数据。随着文件数量的增加,备份元数据对内存的需求也逐渐增大,因此这种分配方式既确保了计算节点的性能,又满足了后台任务对资源的需求。

元数据引擎选型:Redis vs TiKV

起初,我们使用了两个数据引擎:Redis 和 TiKV。在数据量相对较小,即上千万级别的阶段,我们选择了 Redis。当时,由于我们对这些软件并不十分熟悉,我们参考了相关文档,并考虑到 Redis 的上手难度较低、性能较高,且相关资料丰富,因此决定采用它。然而,随着文件数量的迅速增长,Redis 的性能出现了显著的下降。

具体来说,由于我们为 Redis设 置了 RDB 持久化,当内存占用量增加时,Redis 几乎持续处于 RDB 备份状态,这导致了性能的明显下滑。另外,我们当时采用了哨兵模式,并启用了主从复制以增加可用性,但这也带来了问题。由于是异步复制,主节点宕机后,从节点的数据一致性难以保证。

此外,我们了解到客户端并不会从 Redis 的从节点上读取元数据,而是主要依赖主节点进行读写操作。因此,随着文件数量的增加,Redis 的性能进一步下降。

随后,我们考虑并测试了 TiKV 作为元数据引擎的替代方案。从官方文档来看,TiKV 的性能仅次于 Redis,并且在实际使用中,用户层面的体验与 Redis 相差不大。在数据量达到 5 至 6 亿文件的情况下,TiKV 的表现相当稳定。

TiKV 的另一个优势在于其负载均衡和冗余存储的能力。我们采用了三台节点的配置,每个节点都具备多个副本,确保了数据的安全性和可用性。对于运维团队来说,这些特性极大地减轻了工作负担,提高了系统的稳定性和可靠性。

元数据迁移 :从 Redis 到 TiKV

我们于今年一月份左右进行了系统迁移,并已经稳定使用 TiKV 近半年,期间未出现宕机或任何重大问题。

在迁移初期,由于 Redis 难以支撑高达 5 至 6 亿文件的元数据负载,我们决定采用导出与导入的方法来实现迁移。具体地,我们使用了特定的命令将 Redis 中的元数据导出为统一的 JSON 文件,并计划通过 load 命令将其加载到全新的 TiKV 系统中。

然而,在迁移过程中,我们遇到了一个挑战。我们注意到,某个用户的目录由于文件深度过深或其他原因,在导出时遇到了失败。为了解决这个问题,我们采取了一种创新的方法。我们将除问题目录外的其他所有目录分别导出,并手动打开和拼接这些 JSON 文件,以重新构建完整的元数据结构。

在手动处理这些文件时,我们发现元数据的 JSON 文件结构清晰,拼接操作相对简便。其嵌套结构与目录结构基本一致,这使得我们能够高效地处理元数据。最终,我们成功地将这些文件导入到 TiKV 中,完成了迁移过程。

04 为什么使用对象存储 SeaweedFS?

总体而言,我们遵循了 SeaweedFS 官方文档中推荐的主要组件和基本功能,并未涉及过多新颖或高级特性。在具体部署上,我们采用了 CPU 节点作为核心,并在其上运行了 master 服务器。而数据节点则分布运行在不同的物理节点上,每个节点均运行 volume 服务以处理数据存储。此外,我们在相同的 CPU 节点上运行了 filer 服务器,该服务器为 JuiceFS 提供 S3 服务接口,负责与 JuiceFS 进行对接。从目前的运行情况来看,CPU 节点的负载并不重,主要的数据读写和处理任务均分散在各个 worker 节点上。

在数据冗余和备份方面,我们充分利用了 SeaweedFS 的冗余特性。逻辑上,我们将数据节点划分为两个 Rack。当数据写入时,它会在两个 Rack 中都进行写入,确保在 Rack 0 和 Rack 1 中各有一份备份。只有当两个 Rack 都成功写入数据时,才视为写入成功。虽然这种策略使得我们的硬盘容量在逻辑上几乎减半(因为每份数据都要写两份),但它确保了系统的高可用性和数据安全性。即使其中一个 Rack 中的某个节点出现故障或宕机,也不会影响整体的读写操作和数据安全。

SeaweedFS 的优缺点

首先,从上手难度来看,SeaweedFS 相较于工业界广泛使用的 Ceph,显得更为容易操作。其 master、volume 和 filer 等核心组件均可通过编写脚本来轻松启动。用户只需浏览对应的命令参数,并根据实际需求进行配置,随后通过脚本即可完成启动过程。尽管 SeaweedFS 的文档资料相对较少,但其易用性依然值得肯定。

此外,与另一款常用的对象存储系统 Minio 相比,尽管我们未曾直接使用过 Minio,但根据以往案例和介绍,Minio 在处理大量小文件时可能存在一定的不足。因此,我们在选择时并未考虑 Minio。

SeaweedFS 的另一个显著优点在于其安全性和可用性。通过将数据节点划分为两个 Rack,系统实现了数据的冗余备份,从而提高了数据安全性。同时,其master服务器具备自动调度数据写入的功能,能够自动将数据分配到各个 worker 节点上,实现了负载均衡。此外,SeaweedFS 的扩容过程也相对简单,只需新增机器并连接到 master 节点,系统即可自动进行扩容。

此外,SeaweedFS 官方还推荐了一款 master 管理脚本,该脚本配置简单,仅需编写少量配置即可实现定期自动修复数据冗余和平衡数据分布的功能,极大地提高了系统的维护效率。然而,SeaweedFS 的缺点也不容忽视。其文档资料相对较少且较为陈旧,这可能会给新用户带来一定的学习难度。尽管我们在使用过程中并未遇到其他明显的缺点,但这也是未来需要改进的地方。

05 方案实践中遇到的挑战

使用过程中客户端会异常退出

首先,我们曾遭遇客户端异常退出的情况,经过分析发现这是由于内存溢出(OOM)导致的。随着原数据的不断增长,当计算节点未启用 --no-bgjob 选项时,特定节点因执行高内存消耗任务(主要是自动元数据备份)而导致剩余内存不足,进而无法备份原数据,最终引发 OOM 并导致客户端退出。为了解决这个问题,我们在所有计算节点上添加了--no-bgjob 选项,并利用闲置的数据节点作为专门的后台任务处理节点。

首次大文件的读取较慢

其次,我们在使用初期发现了一个性能问题。特别是在首次读取大文件时,发现读取速度远低于千兆网络带宽的极限。经过深入调查,我们发现这是由于在测试对象存储性能时,未正确配置 JuiceFS 命令的参数。我们没有指定 --storage s3 选项,导致测试默认为本地硬盘性能,而非实际的对象存储性能。这一误解导致了我们对对象存储性能的误判。通过进一步检查,我们发现 SeaweedFS Filer 元数据引擎的性能瓶颈,这主要是因为底层使用的是单个机械硬盘。因此,我们将考虑优化这一环节以提升性能。

解压数据集较慢(大量小文件写入)

最后,我们在日常使用中偶尔需要解压数据集,这涉及到大量小文件的写入操作。我们发现这一过程相较于本地解压明显较慢。在与 JuiceFS 官方沟通后,他们建议我们尝试使用 write-back 加速功能。这一功能允许在文件写入后立即返回,而后台则负责将数据上传到对象存储。我们计划在未来实施这一建议以优化解压性能。

希望这篇内容能够对你有一些帮助,如果有其他疑问欢迎加入 JuiceFS 社区与大家共同交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/361106.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[SAP ABAP] 汇总内表数据

在加入新数据记录时&#xff0c;将非数值字段具有相同内容记录的数值字段汇总 语法格式 COLLECT <wa> INTO <itab>. <wa>&#xff1a;代表工作区 <itab>&#xff1a;代表内表 示例1 结果显示&#xff1a;

django restframework 多对多模型 —— python

模型 图书和作者是多对多关系 class Book(models.Model):book_namemodels.CharField(max_length40)pricemodels.DecimalField(max_digits4,decimal_places2)publishmodels.ForeignKey(to"Publish",on_deletemodels.CASCADE,related_name"publish")authorm…

ModuleNotFoundError: No module named ‘gdal‘

第一步检查gdal包是否正确安装&#xff1a; conda list 已经安装显示如下 若查找不到&#xff1a;请按照此说明步骤进行安装&#xff1a;ModuleNotFoundError: No module named ‘osgeo‘_modulenotfounderror: no module named osgeo-CSDN博客 第二步&#xff1a;检查是否可以…

VSCode运行前端项目-页面404

背景&#xff1a; 通过VSCode运行前端本地项目&#xff0c;运行成功后打开本地链接&#xff1a;http://1x.xxx.x.xxx:9803/ &#xff0c;发现打开的页面重定向到404&#xff1a;http//1xx.xxx.x.xxx:9803/404&#xff1b; 并且控制台出现&#xff1a;Failed to load resource: …

C语言 | 文件操作(下)【必收藏】

文件操作&#xff08;下&#xff09; 5、文件的顺序读写5.1 顺序读写函数介绍5.1.1 fputc与fgetc5.1.2 fputs与fgets5.1.3 fprintf与fscanf5.1.4 fread与fwrite 5.2 对比一组函数 6. 文件的随机读写6.1 fseek6.2 ftell6.3 rewind 7. 文件读取结束的判定7.1 被错误使用的feof 8.…

Redis 备份恢复以及数据迁移

昨晚老板突然在群里发了一张图片&#xff0c;说昨天才用的&#xff0c;怎么今天还要登录&#xff1f;相关人赶紧看看。 我心想让你登录就登录呗&#xff0c;哪来那么多事&#xff1f;本想洗洗睡了。老大突然微信问我说&#xff0c;是不是 Redis 出问题了&#xff1f;怎么用户…

筑梦未来:高考后,专业与学校的天秤两端

前言 2024 年高考落幕&#xff0c;几人欢喜几人愁&#xff0c;作为一个过来人&#xff0c;希望每一个努力的悻悻学子都能得偿所愿&#xff0c;不负年华&#xff0c;报的心仪的志愿。 接下来我将从三个方向进行一些分析建议&#xff0c;在专业与大学排名间做出适当的权衡。 专…

智能语音抽油烟机:置入WTK6900L离线语音识别芯片 掌控厨房新风尚

一、抽油烟机语音识别芯片开发背景 在繁忙的现代生活中&#xff0c;人们对于家居生活的便捷性和舒适性要求越来越高。传统的抽油烟机操作方式往往需要用户手动调节风速、开关等功能&#xff0c;不仅操作繁琐&#xff0c;而且在烹饪过程中容易分散注意力&#xff0c;增加安全隐…

【深度学习】基于因果表示学习的CITRIS模型原理和实验

1.引言 1.1.本文的主要内容 理解动态系统中的潜在因果因素&#xff0c;对于智能代理在复杂环境中进行有效推理至关重要。本文将深入介绍CITRIS&#xff0c;这是一种基于变分自编码器&#xff08;VAE&#xff09;的框架&#xff0c;它能够从时间序列图像中提取并学习因果表示&…

Kafka入门-基础概念及参数

一、Kafka术语 Kafka属于分布式的消息引擎系统&#xff0c;它的主要功能是提供一套完备的消息发布与订阅解决方案。可以为每个业务、每个应用甚至是每类数据都创建专属的主题。 Kafka的服务器端由被称为Broker的服务进程构成&#xff0c;即一个Kafka集群由多个Broker组成&#…

薄冰英语语法学习--名词2-格

名词后面 s&#xff0c;代表后面这个东西属于前面的。 比如toms book&#xff0c;汤姆的书。 末尾是s&#xff0c;那么直接在最后加就行了。比如boys&#xff0c;男孩们的 表示几个词共同 的所有关系在最后一个词的词尾加 sMary and Toms books 玛丽和汤姆共有的书表示几个词…

Android简介-历史、API等级与体系结构

1. Android简介 Android是一种基于Linux内核的自由及开放源代码的操作系统。最初是由安迪鲁宾(Andy Rubin)开发的一款相机操作系统。2005年8月被Google收购。2007年11月&#xff0c;Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。…

TCP: 传输控制协议

TCP: 传输控制协议 TCP的服务TCP 的首部小结 本系列文章旨在巩固网络编程理论知识&#xff0c;后续将结合实际开展深入理解的文章。 TCP的服务 T C P和U D P都使用相同的网络层&#xff08;I P&#xff09;&#xff0c;T C P却向应用层提供与U D P完全不同的服务。 T C P提供一…

51单片机STC89C52RC——8.2 8*8 LED点阵模块(动态图像)

目的/效果 在《51单片机STC89C52RC——8.1 8*8 LED点阵模块&#xff08;点亮一个LED&#xff09;》我们点亮一个LED&#xff0c;接下来我们将在8*8的矩阵中展示动态的图像。 1&#xff1a;单列展示&#xff1a; 2&#xff1a;单行展示 3&#xff1a;笑脸 4&#xff1a;右移…

JavaScript的学习之文档的加载

目录 一、onload的运用 浏览器在加载一个页面时&#xff0c;是按照自上而下的顺序加载的&#xff0c;读取到一行就执行一行&#xff0c; 如果script标签写到页面的上方&#xff0c;在代码执行时&#xff0c;页面还没有加载&#xff0c;所以要将JS代码写道页面下面 一、onload的…

Python使用attr库打造数据类,你还在手写构造函数吗?

1、attr库基础介绍 🛠️ 1.1 attr安装与导入 在Python中,attr库是一个简化创建数据类的工具 ,它通过简洁的语法自动添加属性和方法 ,如getter、setter等。要开始使用attr,首先需要通过pip安装这个库。打开终端或命令提示符,运行以下命令进行安装: pip install attrs…

2024软件设计师笔记之考点版(一考就过):11-25

软件设计师之一考就过:成绩版 考点11:防火墙、入侵检测 真题1:(专家系统、模型检测、简单匹配)属于入侵检测;而漏洞扫描不属于。 真题2:防火墙特性包括(控制进出网络的数据包和数据流向、提供流量信息的日志和审计、隐藏内部IP以及网络结构细节),但不包括提供漏洞扫…

「6.25更新日志」JVS·智能BI、逻辑引擎(服务编排)功能更新说明

项目介绍 JVS是企业级数字化服务构建的基础脚手架&#xff0c;主要解决企业信息化项目交付难、实施效率低、开发成本高的问题&#xff0c;采用微服务配置化的方式&#xff0c;提供了 低代码数据分析物联网的核心能力产品&#xff0c;并构建了协同办公、企业常用的管理工具等&am…

AttributeError: module ‘numpy‘ has no attribute ‘long‘

我使用的numpy版本是1.26.4。numpy.long在numpy 1.20就不维护了&#xff0c;numpy 1.24就移除掉了&#xff0c;因此解决方案之一就是重新安装numpy 或者&#xff0c;ctrl鼠标左键定位到报错的地方&#xff0c;将numpy.long改为numpy.longlong。 https://numpy.org/devdocs/rele…

NetSuite Account Merge 科目合并功能分析

最近项目中&#xff0c;客户有提到过能否将不用的Account与新建的Account进行合并&#xff0c;即我们所说的Merge功能&#xff5e;可以&#xff0c;但是该功能有使用的限制&#xff0c;比如最直接的一点需要注意&#xff0c;不同类型的Account是不可以使用Merge功能的&#xff…