大模型训练的算力规模持续扩张,GPU 算力不断提升的同时,数据访问瓶颈对系统整体性能的影响愈发突出。本地存储性能优异但扩展性有限,对象存储在成本与扩展性上具备优势,却在海量小文件、高并发场景下面临吞吐不足的问题,团队往往需要在二者之间艰难取舍。
为此,分布式文件系统成为平衡高性能与可扩展性的关键方案。JuiceFS 已在多行业 AI 场景中广泛落地,其分布式架构能够在大规模数据访问场景下,同时兼顾高性能、强扩展与低成本。本文将从性能角度介绍 JuiceFS 的架构设计,分析不同访问模式下的核心性能瓶颈与优化方法。文中关键知识点均附对应详情链接,为用户理解 JuiceFS 性能机理、掌握常见调优方向提供参考。
01 从架构看 JuiceFS 的性能基础
JuiceFS 分为社区版与企业版,二者整体架构一致,均采用元数据与数据分离的存储架构。客户端采用富客户端设计,承载包括部分元数据处理在内的多项核心逻辑,并同时提供元数据缓存与数据缓存能力,各模块协同工作以实现数据的高效定位与访问。底层数据存储基于对象存储构建,并可借助本地缓存进一步提升访问性能。对外接口上,JuiceFS 支持多种接入方式,其中 FUSE 最为常用,同时也兼容各类 SDK 与 S3 网关。
社区版定位为通用文件系统,用户可根据需求选择不同的元数据引擎。小规模部署可选择 Redis,实现轻量、高响应的数据管理;大规模文件场景可选择 TiKV,以获得良好的横向扩展能力。(参考:JuiceFS 元数据引擎选型指南)
企业版面向复杂高性能场景,相较于社区版,最大的差异有两方面:企业版采用自研多分区元数据引擎,基于 Raft 构建纯内存集群,延迟低且横向扩展能力强,可支持 5,000 亿文件规模。相比社区版需多次 KV 请求完成的操作,企业版通常仅需一次或两次,并可在元数据集群内部处理复杂逻辑。其次,企业版支持分布式缓存共享:同组客户端可在同一区域内互访本地缓存,基于一致性哈希实现,提高缓存命中率和访问效率。在多节点高并发场景下,缓存空间可横向扩展,任务执行前可预热大部分所需数据,从而加速 AI 训练与推理,提高系统性能和稳定性。(JuiceFS 企业版 5.3 特性详解:单文件系统支持超 5,000 亿文件,首次引入 RDMA)
数据分块设计
JuiceFS 将数据切块后存储于对象存储,这一设计是其提升性能的关键,将影响数据读取效率、缓存命中率及高并发访问下的吞吐能力。
JuiceFS 会将文件拆分为多个 chunk。在每个 chunk 内部,系统维护管理结构 slice,用于跟踪数据写入和更新。当文件发生写入时,新数据不会覆盖已有 slice,而是以新的 slice 追加到 chunk 上层。
理想情况下,每个 chunk 最终只应包含一个 slice。每个 slice 由若干 4 MB 的 block 组成,这些 block 是最终存储到对象存储的最小单元。默认情况下,缓存系统也以 block 为单位进行管理。
从右上方示意图可以看出,文件更新采用追加式写入:红色部分为已有 slice,新数据以新的 slice 叠加。读取时,系统组合各层 slice 形成当前视图;碎片过多时,再通过 compaction 合并,以优化访问性能。更多关于数据分块的细节可参考文档。
缓存体系
相较于直接访问对象存储,JuiceFS 的性能提升在很大程度上得益于其缓存体系。JuiceFS 客户端配备了高性能的本地缓存模块,与之相关的配置项如下:
- cache-dir:用于指定缓存目录;
- cache-size:用于设定用于缓存的空间大小;
- prefetch:这是缓存模块中的一个参数,负责预取功能。当某一请求命中某个 block 时,会启动一个后台线程,将整个块完整拉取下来;
- write back 相关配置:用于提高写 IOPS,将需要上传至对象存储的数据块,先写入本地缓存,再异步上传至对象存储。
企业版还具备一些进阶配置,例如通过 cache group 指定一批客户端,将它们的本地缓存配置为同一个分布式缓存组,实现缓存数据的共享。此外,no sharing 是与缓存组相关的配置,启用 no sharing 后,客户端仅从指定的缓存组读取数据,但不作为缓存组成员提供数据读取服务。如此一来,便形成了两级缓存:第一级是本地缓存,第二级是缓存组中其他节点上的缓存。
另一个提升性能的机制是内存 buffer(读 buffer),具有以下作用:
- 合并 IO 请求:可内存层面合并多个连续的 IO 请求。例如,系统发出三个 IO 请求,经内存缓存处理后,实际发出的可能仅有一个;
- 自适应预读功能:在大文件顺序读取场景下,自适应预读功能通过预读来提升请求并发度,从而充分利用缓存和对象存储资源,提高整体 I/O 性能。
企业版还有一些进阶配置:
- max read ahead:用于设定预读的最大范围。
- initial read ahead: 用于设置开启预读时的预读窗口大小,默认以 4MB 块为单位。
- read ahead ratio: 是去年新增的配置,用于控制大文件随机读取时的预读比例,减少读放大导致的带宽瓶颈。过于激进的预读可能对随机读取性能产生负面影响,read ahead ratio 可用于缓解该问题。在 AI 场景中,遇到大文件顺序或随机访问导致的带宽或 IOPS 瓶颈时,可通过调整这些参数优化整体性能。
02 JuiceFS 基准 I/O 测试与瓶颈分析
在介绍 JuiceFS 在常见 AI 场景下的性能调优之前,先通过连续读和随机读基准测试观察系统在理想条件下的 I/O 表现,以理解不同访问模式下的吞吐量与延迟,为后续 AI/ML 场景的读写模式提供参考。
连续读性能
在 JuiceFS 中,连续读的性能通常主要受带宽因素影响。在冷读场景下,性能主要受对象存储带宽约束;而在分布式缓存场景下,网络带宽可能成为瓶颈。例如,一台配备 40 Gbps 网卡的机器,其实际可用带宽可能不足 5 Gbps。此外,FUSE 层的用户态与内核态转换开销也会限制单线程吞吐,经测试单线程读取文件的带宽约为 3.5 Gbps。要突破此限制,需要采用多线程或多并发策略以充分利用存储与网络资源。
threadsbw(GB/s)bw/threads13.53.526.33.1539.53.1649.72.43614.02.33817.02.131018.61.915211.4JuiceFS 连续读性能测试
在性能测试中,单线程连续读带宽约为 3.5 Gbps,随着线程数增加,整体吞吐量可逐渐接近网络带宽上限。为了方便评估自身环境的性能上限,JuiceFS 提供了 bj bench 子命令,可用于测试对象存储带宽。
在实际业务中,缓存往往比直接访问对象存储更常见。此时,可通过增大 buffer size 提高后台预读请求数,从而提升并发度并改善整体吞吐。例如,将 buffer size 调整至 400 MB(对应 100 个 4 MB 块的后台预读请求)后,并发度显著提升,整体吞吐量随之增强。
随机读性能
低并发随机读
在低并发且非异步访问场景下,每个请求需等待前一个完成后才能发出,因此延迟对整体性能的影响尤为显著。I/O 延迟可能来源于多方面,包括元数据查询延迟、对象存储访问延迟,以及本地缓存或分布式缓存读取延迟。在分析随机读性能时,需要重点关注这些延迟因素。
在 4 KB 随机冷读场景下,若 IOPS 仅为 8,且对象存储延迟约 125 毫秒,则可计算出系统并发度约为 1(8 IOPS × 125 ms ≈ 1000 ms)。
这表明当前处于近似单并发、请求串行阻塞的状态。在这种情况下,优化重点通常不在于进一步提升并发,而在于缩短访问路径、降低单次请求延迟,例如将数据预热至本地缓存。完成预热后,随机读路径可由对象存储切换至本地缓存,IOPS 可提升至约 12,000,接近本地磁盘的 I/O 水平。
高并发随机读
高并发随机读通常发生在并发数较高或采用异步 I/O 的场景下,其性能瓶颈主要体现在 IOPS 限制上。IOPS 包括元数据 IOPS、对象存储 IOPS 以及缓存 IOPS。通过 JuiceFS,可以观察这些指标,从而确定性能瓶颈所在。此外,客户端机器的资源(如 CPU 和内存)也可能对性能产生影响,但这类瓶颈相对容易监测。
在冷读场景下,以通过 Libaio 发起的随机读为例,对象存储侧的 IOPS 上限接近 7,000/s。若启用缓存并完成数据预热,访问路径将由对象存储切换至缓存层,IOPS 可进一步提升至 20,000 以上,说明高并发随机读的瓶颈会随访问路径变化而发生转移。
有兴趣深入了解 JuiceFS 的完整数据访问链路,请参考博客:一文详解 JuiceFS 读性能——预读、预取、缓存、FUSE 和对象存储。
03 常见 AI 场景下的 I/O 特性与性能调优
大文件顺序读场景
大文件顺序读取的典型应用场景之一是模型加载,例如通过 Pickle 序列化保存的 PT 文件。在此过程中,性能受到两方面限制:一方面,Pickle 的反序列化效率决定了数据处理速度;另一方面,数据读取通常为单线程,受 FUSE 带宽上限和 CPU 性能约束。为提升吞吐量,可通过增加并发度实现多线程或分片加载,从而充分利用 I/O 能力。在大文件顺序读取的场景下,若能够将数据集完全缓存至本地,可获得最佳性能;若仅需按需读取数据,则实现相对简单。
关于大文件顺序读场景性能优化,可参考如何构建 70GB/s 吞吐的缓存池
海量小文件场景
在计算机视觉和多模态任务中,训练数据集通常由大量单独文件组成,例如单张图片、视频帧或文本标注文件。这类海量小文件场景对元数据服务的压力较大。
海量小文件场景下,元数据性能影响显著。一方面,每个文件的数据量较小;另一方面,存放大量小文件的目录元数据访问效率较低。对于只读负载,可通过开启客户端元数据缓存并延长缓存周期来提升性能。此外,数据读取层的 IOPS 压力也更大,因为小文件无法充分利用预读机制,导致请求更加碎片化。常用的优化措施包括增加本地缓存容量,对于商业版本可进一步采用横向扩展的分布式缓存集群。由于小文件难以受益于预读机制,其延迟表现也相对较高。
该场景性能优化可参考:海量小文件 + 多云协同:地瓜机器人 JuiceFS 存储优化之路
大文件随机读场景
此类场景在 AI 训练中较为常见,例如按样本随机访问 TFRecord、HDF5 或 LMDB 格式的数据集等。以模型加载为例,若数据集格式为随机读且每次读取的大小为数据集样本大小(如 1MB 至 4MB 的图片或短视频),则预读机制可能导致带宽浪费。此类场景通常可通过多并发加载来突破 IOPS 瓶颈,可采取以下措施:
- 增加数据加载的 reader 线程数。
- 使用异步 IO 提高并发度,尽量打满 IOPS。
- 完善缓存体系,如提前将数据映射至缓存以提高底层 IOPS 性能。
- 调整 read ahead ratio 参数(如设为 0.5),以降低预读带来的带宽浪费。例如,原本 4MB 的顺序读会预读 4MB 数据,调整后仅预读 2MB 数据。
本文从性能角度分析了 JuiceFS 的架构设计、基准 I/O 测试以及在典型 AI 场景下的调优方法,为读者提供关于系统性能的入门参考。JuiceFS 已在大量生产环境中得到应用,其分布式架构在性能与成本之间提供了可行的平衡方案。
欢迎在评论区分享或讨论实际使用中的经验与策略。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |