ossfs 2.0.8 及以后版本支持本地数据缓存,通过将读取过的文件数据缓存到本地磁盘,加速后续的重复读取并降低 OSS 请求量。本文介绍本地数据缓存的工作原理、配置方法与性能表现。
背景信息
使用 ossfs 2.0 访问 OSS 时,每次读取文件都需要从远端拉取数据。对于 AI 训练、模型加载等需要多轮重复读取相同数据的场景,频繁的远端访问会带来较高的网络时延和带宽消耗。
ossfs 2.0 的本地数据缓存通过在本地磁盘保留已读取过的文件数据,使后续访问直接从本地获取,从而显著提升重复读性能、降低 OSS 请求费用。
ossfs 2.0 本地数据缓存具备以下特点:
-
性能更优:大文件、小文件重复读场景下带宽均显著优于 ossfs 1.0,具体可见下文性能对比。
-
自动淘汰:内置 LRU 淘汰策略,缓存写满时自动回收最久未访问的文件,无需手动清理。
-
海量小文件支持:配合元数据缓存(
--max_inode_cache_count、--attr_timeout),可大幅加速 AI 训练数据集的多轮加载。
本地数据缓存仅用于读缓存,不影响写路径——写入操作不经过本地缓存。这与 ossfs 1.0 的 -ouse_cache 不同,后者会同时缓存读写数据。
工作原理
缓存粒度
缓存以 OSS 对象(文件)为基本单位。每个被读取过的文件在缓存目录中对应一个缓存文件,采用按需填充的方式。
读取流程
-
首次读取:数据从 OSS 拉取并同步写入本地缓存目录。
-
后续读取:直接从本地缓存读取。
空间回收
当缓存接近容量上限时,自动按 LRU(最近最少使用)策略淘汰旧文件,腾出空间给新数据,回收操作以单个缓存文件为最小单位进行。
配置方法
|
配置项 |
是否必填 |
说明 |
默认值 |
|
disk_data_cache_dir |
否 |
本地缓存目录路径。配置为非空时启用数据缓存。 |
空 |
|
disk_data_cache_size |
条件必填 |
缓存容量上限,按 GiB 对齐。不可超过缓存目录所在磁盘/分区的可用空间。disk_data_cache_dir 可以为空;disk_data_cache_dir 指定之后,本参数必须填入合法值。 |
空 |
|
disk_data_cache_io_engine |
否 |
磁盘缓存 IO 引擎,可选 psync 或 libaio。 |
psync |
约束:
-
--disk_data_cache_dir 指向的目录必须存在且为空目录,尽量保证缓存路径为独立分区 / 独立盘。
-
--disk_data_cache_size 不可超过缓存目录所在磁盘的可用空间。
-
同一台机器上挂载多个 ossfs2 实例时,每个实例必须使用独立的缓存目录。
-
ossfs2 进程退出时不会自动清理缓存目录,需要手动清理。
-
挂载后尽量不要对缓存目录路径进行操作,避免发生未知错误。
挂载命令示例:
ossfs2 mount /mnt/oss/ \
--oss_bucket <your-bucket> \
--oss_endpoint <your-endpoint> \
--oss_access_key_id <ak> \
--oss_access_key_secret <sk> \
--disk_data_cache_dir /mnt/disk/ossfs2/cache \
--disk_data_cache_size 256G
环境要求
|
参数 |
要求 |
|
缓存盘文件系统 |
ext4、xfs 或 tmpfs(仅限 psync 模式),其他文件系统未验证 |
|
缓存盘类型 |
推荐弹性临时盘 / 本地 NVMe;ESSD PL0/PL1/PL2 的吞吐容易成为瓶颈,此时使用体验可能较差;内存充裕时可使用 tmpfs(仅限 psync) |
|
缓存盘可用空间 |
不小于 --disk_data_cache_size 设定的值 |
使用建议
本地数据缓存适用于“读多写少”且需要重复访问相同数据的场景。
IO 引擎(disk_data_cache_io_engine)配置建议:
-
psync:使用同步读写系统调用,读取时数据会经过操作系统 PageCache。当缓存数据量接近或小于可用内存时,热数据自然驻留在 PageCache 中,可获得接近内存的读取速度。适用于通用场景、低规格云盘以及 tmpfs 缓存盘(tmpfs 不支持 libaio)。
-
libaio:使用 Linux 异步 IO 接口,绕过 PageCache 直接操作磁盘。适用于大容量本地 NVMe + 数据集远大于内存的场景,相比 psync 通常有 20% 左右的额外提升。
下表列出典型场景及推荐配置:
|
场景 |
使用建议 |
|
AI 训练数据多轮加载(多 epoch 重复访问同一数据集)、固定数据集多次查询 / 分析 |
启用本地数据缓存,按数据集大小×1.1 设置 --disk_data_cache_size。缓存盘为本地 NVMe 且数据量较大时,推荐 --disk_data_cache_io_engine=libaio,充分发挥磁盘性能。 |
|
大模型推理 / vLLM 加载(GB 级模型文件反复加载) |
推荐机型内存大于模型总大小时,使用 tmpfs 盘作为缓存盘。若内存不足以全缓存模型文件,也可选择本地盘作为缓存盘,但此时性能会受盘性能限制,需要具体评估后判断是否开启本地数据缓存。 |
若对数据实时性要求高且数据频繁修改的场景下,不建议开启数据缓存(缓存存在一定时效性差异)。
性能对比
测试对象:ossfs 2.0.9 vs ossfs 1.91.10。表中“首次读 / 后续读”分别对应缓存未命中(需从 OSS 拉取)与命中本地缓存。“—”表示该配置无缓存,不区分首次/后续读。
场景一:大文件顺序读(4 线程读取 100GB 文件)
测试环境
-
机器:ecs.i4.4xlarge(16 vCPU,128 GiB)
-
本地 NVMe 盘:3576 GiB NVMe(读带宽 6 GB/s,写带宽 3 GB/s,IOPS 90w)
-
ossfs 2.0:--disk_data_cache_dir=<path> --disk_data_cache_size=3T,分别测试 --disk_data_cache_io_engine=psync 和 libaio
-
ossfs 1.0:-ouse_cache=<path> -oparallel_count=128
结果
|
配置 |
io 模式 |
带宽(首次读 / 后续读) |
CPU (avg/max) |
峰值内存 |
|
ossfs 2.0(无缓存) |
- |
2841 MB/s — |
385% / 468% |
5170 MB |
|
ossfs 2.0 |
psync |
2561 / 4516 MB/s |
371% / 526% |
2118 MB |
|
libaio |
2343 / 6625 MB/s |
298% / 322% |
2146 MB |
|
|
ossfs 1.0 |
- |
1249 / 2648 MB/s |
815% / 1214% |
137 MB |
结论:
-
启用缓存后,ossfs 2.0 在大文件后续读场景下相比 ossfs 1.0 性能提升约 2.5 倍(libaio 模式 6625 vs 2648 MB/s),可达到本地 NVMe 性能上限;同时 CPU 占用大幅降低(≈300% vs 800%)。
场景二:海量小文件读取(ImageNet 训练数据集加载)
测试环境
-
机器:ecs.i4.32xlarge(128 vCPU,1024 GiB)
-
本地 NVMe 盘:8 × 3576 GiB NVMe
-
数据集:ImageNet 训练集(约 1.3M 张图片),多 epoch 重复加载
-
ossfs 2.0:--disk_data_cache_dir=<path> --disk_data_cache_size=1500G --disk_data_cache_io_engine=libaio --attr_timeout=36000 --max_inode_cache_count=11000000(启用元数据缓存)
-
ossfs 1.0:-ouse_cache=<path> -oreaddir_optimize -omax_stat_cache_size=11000000 -ostat_cache_expire=72000
结果
|
配置 |
带宽(首次读 / 后续读) |
CPU (avg/max) |
峰值内存 |
|
ossfs 2.0(无缓存) |
304 MB/s —(约 2400 img/s) |
67% / 209% |
5062 MB |
|
ossfs 2.0 |
286 / 1292 MB/s(约 10000 img/s) |
219% / 1068% |
6470 MB |
|
ossfs 1.0 |
38 / 224 MB/s(约 2000 img/s) |
66.1% / 206% |
31.6 GB |
结论:
-
启用磁盘缓存 + 元数据缓存后,ossfs 2.0 后续 epoch 加载性能达到无磁盘缓存的 4.25 倍(1292 vs 304 MB/s),且完全消除 OSS 网络请求。多轮重复加载相同数据集的 AI 训练负载,强烈推荐使用 ossfs 2.0 本地缓存 + libaio。