[云原生/分布式/文件系统] JuiceFS:云原生环境下的高性能 POSIX 分布式文件系统(可与Lance/Iceberg等数据湖融合)
1 概述:JuiceFS
产品介绍
- JuiceFS 是一款基于 Apache License 2.0 协议开源的高性能 POSIX 文件系统,专为云原生环境特别优化设计。它采用数据与元数据分离的架构:【文件数据】持久化存储到【对象存储】(如 Amazon S3、阿里云 OSS 等),而【元数据】则持久化到多种兼容的【数据库引擎】中(如 Redis、MySQL、TiKV 等)。


- 产品定位:面向云原生环境的分布式共享文件系统,旨在将海量云端存储直接对接到大数据、机器学习、人工智能以及各类应用平台的生产环境中

-
诞生的背景与原因:
- 传统分布式文件系统(如 HDFS、CephFS)在云环境下部署复杂、成本高昂,且与对象存储的衔接不自然
- 对象存储虽然成本低、容量无上限,但缺乏 POSIX 文件系统语义,无法直接被传统应用使用
- 市场上缺少一种既兼容 POSIX 语义、又能充分利用对象存储成本优势的方案
- JuiceFS 的设计灵感来自 Google File System、HDFS 和 MooseFS,旨在填补这一空白
-
解决的核心问题:
- 存储成本:利用廉价的对象存储作为数据层,大幅降低存储成本
- 共享访问:支持数千客户端同时读写,提供强一致性
- POSIX 兼容:让现有应用无需修改即可使用云端存储
- 多云/混合云:支持 30+ 种对象存储,适配公有云、私有云和混合云
-
URLs:
基于云原生环境
- JuiceFS 的"云原生"体现在四个层面:
不自带存储、以【对象存储】为底座、以【容器】生态为首选运行环境、【跨云】可迁移——这就是 JuiceFS 的云原生本质。
| 维度 | 云原生体现 |
|---|---|
| 存储解耦 | 数据与元数据分离,数据层复用云上已有的对象存储(S3/OSS/COS 等 30+ 种),不自带存储池,天然适配云的弹性按量付费模型 |
| K8s 原生 | 提供成熟的 CSI Driver(下载量 500 万+),作为 PersistentVolume 直接挂载,支持 Sidecar、Mount Pod 共享、Operator 缓存预热等云原生范式 |
| 多协议弹性接入 | FUSE / Hadoop SDK / CSI / S3 Gateway / WebDAV / Python SDK,容器、大数据、AI 框架各取所需,无状态客户端可随时拉起/销毁 |
| 多云/混合云无锁定 | 同一文件系统可跨可用区、跨云厂商共享,客户端可弹性扩缩容,不绑定特定基础设施 |
发展历程
| 时间 | 里程碑 |
|---|---|
| 2021 年 1 月 | JuiceFS 正式开源,以 Apache 2.0 协议发布(最初为 AGPLv3) |
| 2022 年 1 月 | 开源协议从 AGPLv3 更改为 Apache 2.0(PR #1282),大幅降低使用门槛 |
| v1.0 | 首个正式 GA 版本,核心功能趋于稳定,存储格式定型 |
| v1.1 | 新增 --storage-class、--update-fstab、目录统计、--open-cache-limit 等功能 |
| v1.2 | S3 Gateway 支持多用户管理;引入 ACL、--upload-hours、--backup-skip-trash 等 |
| v1.3(LTS) | 2025 年发布,继开源以来第四个重要版本。支持 Python SDK、Windows 客户端大幅优化、1 亿文件备份分钟级完成、集成 Apache Ranger、SQL/TiKV 元数据引擎性能提升 |
| v1.4(LTS) | 2026 年 7 月发布,第五个主要版本,维护 24 个月。引入存储分层、用户/组配额管理、可恢复同步检查点机制、元数据操作变更日志、CIFS/SMB 支持、Hadoop Kerberos 认证、SM 加密支持等企业级特性 |
| 2025 年度 | 社区版数据量增长 89% 超 1.3 EB;GitHub Star 超 12.6K;文件系统 590K+,活跃客户端 150K+,文件数量 4000 亿+;营收连续第三年 100% 增长 |
| 企业版 5.2 | 2025 年上半年发布,单卷突破千亿文件规模,1 毫秒元数据时延;100 台 100Gbps 节点聚合读带宽达 1.2 TB/s |
| 企业版 5.3 | 2025 年下半年发布,分区限制从 256 提升至 1024,支持单卷超 5,000 亿文件;首次引入 RDMA 技术(实验阶段) |
主要功能
文件系统核心功能
- 完全 POSIX 兼容:通过 8813 项 pjdfstest 兼容性测试,可作为本地文件系统无缝对接现有应用
- 强一致性:确认的修改在所有挂载服务器立即可见,提供 close-to-open 一致性模型
- 全局文件锁:支持 BSD locks(flock)和 POSIX record locks(fcntl)
- 扩展属性(xattr):支持文件扩展属性
- POSIX ACL:v1.2 起支持 POSIX ACL 细粒度权限管理
- 原子操作:原子的 rename 和元数据操作
- Mmap 支持:完整的 mmap 读写支持
- Fallocate punch hole:支持 punch hole 操作
- 硬链接与符号链接:完整支持
多协议接入
| 接入方式 | 说明 |
|---|---|
| FUSE 挂载 | POSIX 兼容方式挂载到 Linux/macOS/Windows,作为本地文件系统使用 |
| Hadoop Java SDK | 兼容 Hadoop 2.x 和 3.x,可直接替代 HDFS |
| Kubernetes CSI Driver | 为 K8s 集群提供海量持久化存储 |
| S3 Gateway | 提供 S3 兼容接口,支持 AWS CLI、s3cmd、MinIO client 等工具 |
| WebDAV | 通过 HTTP 协议以 RESTful API 方式接入 |
| Python SDK | v1.3 新增,原生实现 fsspec,便于接入 Ray 等框架 |
| Docker Volume | 作为 Docker 持久卷使用 |
数据管理与安全
- 数据压缩:支持 LZ4 或 Zstandard 压缩,在 Block 上传前进行
- 数据加密:支持传输中加密和静态加密(RSA + AES256-GCM),v1.4 新增 SM 国密加密
- 回收站:默认开启,删除文件后保留指定天数,支持恢复
- 配额管理:目录级配额;v1.4 新增用户级和组级配额
- 存储分层:v1.4 引入多级存储分层,支持配置不同存储类
- 数据备份:元数据自动备份到对象存储,1 亿文件分钟级完成
- Apache Ranger 集成:支持大数据场景的细粒度权限管理
- 快照:在路线图中规划
运维与监控
- 内置基准测试:提供子命令运行性能基准测试
- Prometheus 监控:支持 Prometheus 指标导出和
remote_write协议 - Consul 集成:支持服务发现
- 匿名使用数据:默认收集匿名使用数据,可通过
--no-usage-report禁用
核心优势
-
极高的 POSIX 兼容性:通过全部 8813 项 pjdfstest 测试,几乎所有不依赖特定文件系统的应用都能直接运行
-
存储成本极低:利用对象存储作为数据层,成本仅为传统分布式文件系统的一小部分。
- 例如,百图生科使用 JuiceFS 后存储成本降低 90%
-
卓越的性能表现:
- 元数据访问延迟低至 1-3 毫秒(企业版千亿文件规模下保持 1 毫秒)
- 数据访问延迟取决于对象存储(通常 20-100 ms)
- 顺序读写吞吐量可达 50 MiB/s 至 2800 MiB/s
- 相比 EFS 和 S3FS,提供 10 倍以上的吞吐量
- 企业版在 100 台 100Gbps 节点下聚合读带宽达 1.2 TB/s
-
多元数据引擎支持:Redis、MySQL/MariaDB、PostgreSQL、SQLite、TiKV、FoundationDB、etcd 等,灵活适配不同规模和场景
-
海量对象存储兼容:支持 30+ 种对象存储,包括所有主流公有云和私有化方案
-
覆盖写性能优异:采用追加写新 Block + 更新元数据的方式,避免 CephFS 式的读-改-写开销
-
云原生生态完善:CSI Driver 下载量超 500 万次,Kubernetes 集成成熟
-
开源协议友好:Apache 2.0 协议,无商业使用限制
-
跨平台支持:Linux、macOS、Windows 全平台覆盖,支持 x86、ARM 等多种架构
-
AI 场景深度适配:Python SDK + fsspec 兼容、分布式缓存、海量小文件优化
主要短板
- 随机写性能有待提升:随机写会产生文件碎片(多个重叠 Slice),影响读性能。虽然后台会异步运行碎片合并,但短时间内大量覆盖写仍可能导致性能下降
- 分布式缓存仅限企业版:社区版不支持分布式缓存功能,大规模 AI 训练场景下可能需要企业版
- 元数据引擎运维负担:需要额外维护一个元数据引擎(Redis/MySQL/TiKV 等),增加了系统复杂度
- 单文件系统绑定单个对象存储:不支持一个文件系统同时绑定多个不同的对象存储(虽然支持同一对象存储的多个 bucket 分片)
- 无法直接访问对象存储已有数据:JuiceFS 有自己的数据组织格式,不能直接读取对象存储中已有的原始文件,需要通过
juicefs sync迁移 - FUSE 性能开销:作为用户态文件系统,FUSE 层会引入少量性能开销
- 压缩算法不可更改:一旦格式化时设定压缩算法,后续不可修改,否则会导致读取已有数据失败
- 加密密钥不可更改:RSA 私钥设定后不可更改
- Windows 平台需额外依赖:需安装 WinFsp 才能实现 FUSE 挂载
- macOS 平台需额外依赖:需安装 macFUSE 才能实现 FUSE 挂载
局限性
- 不适合作为块存储使用:JuiceFS 是文件系统,不提供块设备接口
- 不适合超低延迟场景:由于数据层依赖对象存储,数据访问延迟(20-100 ms)无法达到本地 NVMe 或全闪存分布式文件系统的水平
- 不适合完全离线环境:需要对象存储作为数据层,纯离线场景下需自建 MinIO/Ceph 等对象存储
- 社区版无快照功能:快照功能仍在路线图中,目前仅企业版有类似能力
- 大目录 listing 性能:单目录内大量文件时,listing 性能受限于元数据引擎能力
- 对象存储 API 调用费用:大量小文件场景下,对象存储 API 调用次数可能带来额外费用
- 会话管理开销:客户端需要定期发送心跳维护会话,在极高并发下元数据引擎压力较大
适用场景
强烈推荐
- AI/ML 训练与推理:海量训练数据存储、模型文件管理、checkpoint 存储。已有大量成功案例(智谱 AI、阶跃星辰、携程、百图生科等)
- 大数据分析:替代 HDFS 提供低成本存储,兼容 Hadoop 生态
- Kubernetes 持久化存储:为容器化应用提供共享存储,CSI Driver 成熟
- 多云/混合云存储:跨可用区、跨云共享文件系统
- 自动驾驶数据管理:亿级文件存储(九识智能、酷睿程等案例)
- 生命科学/生物信息:大模型训练数据平台(百图生科案例)
- 量化投资:高性能存储平台(Ariste AI 使用 JuiceFS + MinIO)
适合使用
- 日志归档:低成本长期存储
- 媒体处理:视频/图片文件的共享读写
- DevOps 文件共享:CI/CD 流水线中的构建产物共享
- 科学计算:Ray/MPI 等框架的数据存储
不太适合
- 数据库存储:需要超低延迟和块设备接口
- 高频小文件随机写:会产生大量碎片,虽然有后台合并但仍有性能影响
- 单机本地存储:如果不需要共享和海量容量,本地文件系统更简单高效
同类竞品
| 特性 | JuiceFS | CephFS | MinIO | SeaweedFS | AWS EFS | Alluxio |
|---|---|---|---|---|---|---|
| 定位 | 云原生 POSIX 文件系统 | 统一分布式存储系统 | 高性能对象存储 | 分布式文件+对象存储 | 托管 NFS 文件系统 | 数据编排与缓存层 |
| 数据存储 | 对象存储(30+种) | RADOS Pool(自管) | 对象存储(自管) | 本地磁盘/卷 | AWS 托管 | 多源(对接现有存储) |
| 元数据引擎 | Redis/MySQL/TiKV/SQL 等 | MDS(自管) | 内置 | Volume Manager | AWS 托管 | 内置 |
| POSIX 兼容 | ✓(8813 项测试) | ✓ | ✗(S3 API) | 部分 | ✓(NFS) | ✓(FUSE) |
| Hadoop 兼容 | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ |
| S3 兼容 | ✓(Gateway) | ✓(RGW) | ✓(原生) | ✓(S3 API) | ✗ | ✓ |
| K8s CSI | ✓ | ✓ | ✓ | ✗ | ✓(EFS CSI) | ✓ |
| 数据压缩 | ✓(LZ4/Zstd) | ✓(BlueStore 层) | ✓ | ✓ | ✗ | ✗ |
| 数据加密 | ✓(RSA+AES/SM) | ✓(Messenger v2) | ✓ | ✗ | ✓(托管) | 取决于后端 |
| 客户端缓存 | ✓ | ✗ | ✗ | ✗ | ✗ | ✓(核心能力) |
| 覆盖写性能 | 优秀(追加+元数据更新) | 较差(读-改-写) | N/A | 一般 | 一般 | 取决于后端 |
| 快照 | 规划中 | ✓ | ✓(版本控制) | ✓ | ✓ | 取决于后端 |
| 开发语言 | Go | C++ | Go | Go | 托管 | Java |
| 开源协议 | Apache 2.0 | LGPL v2.1/v3 | AGPLv3 | Apache 2.0 | 闭源 | Apache 2.0 |
| 部署复杂度 | 中(需元数据引擎+对象存储) | 高(完整 Ceph 集群) | 中 | 低 | 极低(托管) | 中 |
与 CephFS 的关键区别
- 架构理念:CephFS 是一套完整且独立的系统,所有数据存储在自有 RADOS Pool 中;JuiceFS 是一个轻量级客户端,复用已有对象存储和数据库
- 覆盖写:CephFS 需直接修改对应 objects,EC/压缩时还需先读后写,开销大;JuiceFS 将更新数据作为新 objects 写入并更新元数据即可,性能大幅提升
- 数据压缩:CephFS 依赖 BlueStore 层压缩;JuiceFS 在 Block 上传前压缩,甚至可以对接 RADOS 实现双重压缩
- 数据加密:CephFS 依赖 Messenger v2 和 OSD 层加密;JuiceFS 在客户端侧加解密,对对象存储完全透明
- 部署模式:CephFS 适合私有云部署;JuiceFS 适合公有云、私有云、混合云
发展趋势
开源社区活跃趋势
- GitHub Star:截至 2025 年底超 12.6K,持续稳定增长
- 下载量:JuiceFS 客户端下载量超 5 万次,CSI Driver 下载量超 500 万次
- 社区规模:中文社区 10 个微信群组,Slack 英文社区超千人
- 贡献者:2025 年有 60 位贡献者参与,新增 305 个 Issue,合并 601 个 PR
- v1.4 参与度:57 位贡献者贡献了 520 次提交
- 用户增长:
- 文件系统数量 590K+,年增长 82%
- 活跃客户端 150K+,年增长 46%
- 文件数量 4000 亿+,年增长 43%
- 数据总量 1.3 EiB+,年增长 89%
- 营收增长:连续第三年 100% 增长,为社区持续投入提供保障
Star 与 Fork 趋势
- Star 数从开源初期的快速增长,到目前进入稳步增长阶段
- Fork 数稳定增长,反映社区参与度持续提升
- CSI Driver 的下载量(500 万+)远超客户端本身(5 万+),表明 Kubernetes 生态是最大的使用入口
项目发展趋势
JuiceFS 正从开源新秀成长为 AI 时代最受信任的云原生文件系统之一,社区版持续聚焦通用性与 AI 场景适配,企业版向千亿甚至 5,000 亿文件规模迈进,整体生态高速增长、社区活跃度持续攀升。
2 工作原理与架构
概念术语
| 术语 | 说明 |
|---|---|
| Volume(文件系统) | 一个独立的 JuiceFS 命名空间,由格式化创建 |
| Client(客户端) | JuiceFS 挂载进程,协调元数据引擎和对象存储,实现文件系统接口 |
| Metadata Engine(元数据引擎) | 存储文件元数据的数据库引擎,如 Redis、MySQL、TiKV 等 |
| Data Storage(数据存储) | 存储文件数据的对象存储或本地磁盘 |
| Chunk | 文件分割的逻辑单位,固定 64 MiB,用于大文件快速定位 |
| Slice | 数据写入的逻辑单位,变长,每次连续写入分配一个 Slice,不能跨越 Chunk 边界 |
| Block | 文件分割后的物理存储最小单位,默认 4 MiB(可配置 64 KiB ~ 16 MiB),与对象存储中的 object 一一对应 |
| SliceRef | Slice 的引用计数记录,用于垃圾回收 |
| Session | 客户端会话,通过心跳维护,只读客户端不记录会话 |
| Trash(回收站) | 删除文件的暂存区,默认保留 1 天 |
| Compaction(碎片合并) | 将同一 Chunk 内多个重叠的 Slice 合并为更少、更连续的 Slice |
| FUSE | Filesystem in Userspace,用户态文件系统接口 |
| Writeback(写缓存) | 数据先写入本地缓存,再异步上传到对象存储 |
架构与运行原理
技术架构(必读)

整体架构
JuiceFS 由三个核心部分组成:
- JuiceFS Client(客户端):所有文件读写、碎片合并、回收站文件过期删除等后台任务均在客户端中发生。客户端同时与对象存储和元数据引擎打交道,支持 FUSE、Hadoop SDK、CSI、S3 Gateway、WebDAV、Python SDK 等多种接入方式
- Data Storage(数据存储):文件数据被切分后上传至对象存储。支持几乎所有公有云对象存储,以及 MinIO、Ceph RGW 等私有化方案
- Metadata Engine(元数据引擎):存储文件元数据,包括常规文件系统元数据(文件名、大小、权限、时间、目录结构等)和文件数据索引(数据分配和引用计数、客户端会话等)
文件存储机制:Chunk → Slice → Block
Chunk(逻辑分块)
- 每个文件由 1 或多个 Chunk 组成,每个 Chunk 最大 64 MiB
- 不论文件多大,所有读写都根据偏移量定位到对应的 Chunk
- 只要文件总长度不变,Chunk 切分固定不变
- 作用:优化大文件的查找定位
Slice(逻辑写入单位)
- 一个 Slice 代表一次连续写入,隶属于某个 Chunk,不能跨越 Chunk 边界
- 顺序写入一个 160 MiB 文件 → 3 个 Chunk,每个 Chunk 仅包含 1 个 Slice
- 多次追加写(每次 flush)→ 每个 Chunk 可能包含多个 Slice
- 相同区域反复修改 → Slice 之间发生重叠
- 读取规则:对于每一处文件位置,读到该位置最新写入的 Slice("从上往下看")
- 碎片化问题:大量重叠 Slice 会显著影响读性能,客户端会异步运行碎片合并
Block(物理存储单位)
- Slice 在持久化时被进一步拆分为 Block,默认 4 MiB(可配置 64 KiB ~ 16 MiB)
- 多线程并发上传以提升写性能
- Block 是对象存储和磁盘缓存的最小存储单元
- 对象命名格式:
${fsname}/chunks/${hash}/${sliceId}_${index}_${size}
在对象存储中看不到原始文件,只有
chunks目录和一堆数字编号的目录和文件。这些数字编号的对象就是经过 JuiceFS 拆分存储的 Block,而 Block 与 Chunk、Slice 的对应关系存储在元数据引擎中。
元数据结构
核心数据结构
| 结构 | 说明 | 关键字段 |
|---|---|---|
| Setting | 格式化信息 | Name, UUID, Storage, Bucket, BlockSize, Compression, TrashDays, Shards 等 |
| Counter | 计数器与任务时间戳 | usedSpace, totalInodes, nextInode, nextChunk, nextSession, nextTrash, 各种 cleanup 时间戳 |
| Session | 客户端会话 | SID 和超时时间,定时心跳更新 |
| SessionInfo | 会话详情 | 版本、主机名、挂载点路径、进程 PID |
| Node (Attr) | 文件属性 | Typ, Mode, Uid, Gid, Atime, Mtime, Ctime, Nlink, Length, Parent 等 |
| Edge | 目录边 | parentInode + name → type + inode |
| Chunk | 数据块元数据 | inode + index → []Slices |
| SliceRef | Slice 引用计数 | sliceId + size → refs(大部分 refs=1,以 refs-1 存储) |
| DelFiles | 待清理文件 | inode + length → expire |
| DelSlices | 延迟删除的 Slices | sliceId + deleted → []slice |
| Sustained | 会话临时保留文件 | sid → []inode |
Slice 结构
type Slice struct {
Pos uint32 // Slice 在 Chunk 中的偏移位置
ID uint64 // Slice 的全局唯一 ID
Size uint32 // Slice 的总大小
Off uint32 // 有效数据在此 Slice 中的偏移位置
Len uint32 // 有效数据在此 Slice 中的大小
}
每个 Slice 编码为 24 字节二进制数据。通过 Off 和 Len 标记有效数据范围,告诉文件系统每个 Slice 中哪些部分是有效的。
三种元数据引擎的存储映射
| 结构 | Redis | SQL | TKV (TiKV) |
|---|---|---|---|
| Setting | setting (String) |
jfs_setting 表 |
setting key |
| Node | i${inode} (String) | jfs_node 表 | A${inode}I key |
||
| Edge | d${inode} (Hash) | jfs_edge 表 | A${inode}D${name} key |
||
| Chunk | c${inode}_${index} (List) |
jfs_chunk 表 |
A${inode}C${index} key |
| SliceRef | sliceRef (Hash) |
jfs_chunk_ref 表 |
K${sliceId}${size} key |
| DelFiles | delfiles (Sorted Set) |
jfs_delfile 表 |
D${inode}${length} key |
| Sustained | session${sid} (List) | jfs_sustained 表 | SS${sid}${inode} key |
数据读写流程
写流程
读流程
Slice 重构机制(读取时的关键操作)
当多个 Slices 有重叠时,读取需顺序遍历 Slices 列表并重构最新版数据分布:
- 有多个 Slice 覆盖的部分以最后加入的 Slice 为准
- 没有被 Slice 覆盖的部分自动补零(sliceId = 0)
- 根据文件 size 截断 Chunk
示例:假设 Chunk 0 中有 3 个 Slices:
Slice{pos: 10M, id: 10, size: 30M, off: 0, len: 30M} // 第一次写入
Slice{pos: 20M, id: 11, size: 16M, off: 0, len: 16M} // 第二次写入(覆盖部分)
Slice{pos: 16M, id: 12, size: 10M, off: 0, len: 10M} // 第三次写入(覆盖部分)
图示(每个 _ 表示 2 MiB):
Chunk: |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
Slice 10: |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
Slice 11: |_ _ _ _ _ _ _ _|
Slice 12: |_ _ _ _ _|
重构后: |_ _ _ _ _|_ _ _|_ _ _ _ _|_ _ _ _ _|_ _|_ _ _ _ _ _ _ _ _ _ _ _|
0 10 12 11 10 0
垃圾回收机制
碎片合并(Compaction)
- 触发条件:文件被多次写入导致同一 Chunk 内出现多个重叠的 Slice
- 合并过程:将旧 Slices 合并压缩为新 Slice,旧 Slices 标记为删除
- 回收站集成:若开启回收站,被 compact 删除的旧 Slices 通过 DelSlices 记录,保留
TrashDays天 - 自动触发:每次读/写文件时都会检查,并在后台任务中进行该文件相关碎片的整理
数据压缩与加密
原始数据 → [压缩 (LZ4/Zstd)] → [加密 (RSA+AES256-GCM/SM)] → 上传到对象存储
- 压缩:在 Block 上传前进行,对象名不变,内容为压缩后结果,不携带元信息
- 加密:对象名不变,内容为 header + 加密数据,Header 记录经 RSA 加密的对称密钥 + 随机种子
- 不可逆:压缩算法和 RSA 密钥一旦设定不可更改
FUSE 实现
- 使用 low-level API(基于 inode),而非 high-level API(基于路径)
- 底层依赖
go-fuse,而非libfuse - 选择 low-level API 的原因:JuiceFS 的元数据按 inode 组织,直接提供基于 inode 的 API,避免 inode↔path 的反复转换开销
多级缓存机制
| 缓存层 | 说明 | 配置参数 |
|---|---|---|
| 元数据缓存 | 属性缓存、目录项缓存、打开文件缓存 | --attr-cache, --entry-cache, --dir-entry-cache, --open-cache |
| 数据读缓存 | 本地磁盘缓存 Block 数据,主动失效 | --cache-dir, --cache-size, --free-space-ratio |
| 写缓存(Writeback) | 数据先写本地缓存,异步上传对象存储 | --writeback, --buffer-size |
| 预读 | 并发预读后续 Block | --prefetch, --max-readahead |
3 使用指南
安装部署
Linux 安装
方式一:一键安装脚本(推荐)
# 默认安装到 /usr/local/bin
curl -sSL https://d.juicefs.com/install | sh -
# 安装到自定义位置(如 /tmp)
curl -sSL https://d.juicefs.com/install | sh -s /tmp
方式二:下载预编译二进制
# 1. 获取最新版本号
JFS_LATEST_TAG=$(curl -s https://api.github.com/repos/juicedata/juicefs/releases/latest | grep 'tag_name' | cut -d '"' -f 4 | tr -d 'v')
# 2. 下载客户端
wget "https://github.com/juicedata/juicefs/releases/download/v${JFS_LATEST_TAG}/juicefs-${JFS_LATEST_TAG}-linux-amd64.tar.gz"
# 3. 解压安装包
tar -zxf "juicefs-${JFS_LATEST_TAG}-linux-amd64.tar.gz"
# 4. 安装客户端
sudo install juicefs /usr/local/bin
# 5. 验证安装
juicefs --help
方式三:包管理器
# Ubuntu PPA
sudo add-apt-repository ppa:juicefs/ppa
sudo apt-get update
sudo apt-get install juicefs
# Fedora Copr
sudo dnf copr enable -y juicedata/juicefs
sudo dnf install juicefs
# Snap
sudo snap install juicefs
# 解除 Snap 沙箱对 FUSE 的限制
sudo ln -s -f /snap/juicefs/current/juicefs /snap/bin/juicefs
# Arch AUR
yay -S juicefs
Windows 安装
前置条件:需先安装 WinFsp(开源 Windows 文件系统代理,提供 FUSE 仿真层)
方式一:预编译客户端
- 从 GitHub Releases 下载
juicefs-x.y.z-windows-amd64.zip - 解压获得
juicefs.exe - 将
juicefs.exe移动到C:\Windows\System32,或放入自定义目录并添加到 PATH
方式二:Scoop
scoop install juicefs
方式三:WSL 中使用 Linux 版客户端
在 WSL 中安装 Linux 版 JuiceFS 客户端,使用方式与 Linux 完全一致。
macOS 安装
前置条件:需安装 macFUSE 才能实现 FUSE 挂载(不使用挂载则无需安装)
# Homebrew 安装
brew install juicefs
# 或下载预编译二进制
# 下载 darwin-amd64 (Intel) 或 darwin-arm64 (M1) 版本
sudo install juicefs /usr/local/bin
Docker 容器
FROM ubuntu:20.04
RUN apt update && apt install -y curl fuse && \
apt-get autoremove && \
apt-get clean && \
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*
RUN set -x && \
mkdir /juicefs && cd /juicefs && \
JFS_LATEST_TAG=$(curl -s https://api.github.com/repos/juicedata/juicefs/releases/latest | grep 'tag_name' | cut -d '"' -f 4 | tr -d 'v') && \
curl -s -L "https://github.com/juicedata/juicefs/releases/download/v${JFS_LATEST_TAG}/juicefs-${JFS_LATEST_TAG}-linux-amd64.tar.gz" \
| tar -zx && \
install juicefs /usr/bin && \
cd .. && rm -rf /juicefs
CMD [ "juicefs" ]
源码编译
# 类 Unix 系统
# 依赖:Go 1.20+、GCC 5.4+
git clone https://github.com/juicedata/juicefs.git
cd juicefs
git checkout v1.4.0 # 切换到正式版本
make
# 编译好的 juicefs 二进制程序在当前目录
# Windows 编译
# 依赖:WinFsp、Go 1.20+、MinGW-w64 (GCC)
git clone https://github.com/juicedata/juicefs.git && cd juicefs
mkdir "C:\WinFsp\inc\fuse"
copy .\hack\winfsp_headers\* C:\WinFsp\inc\fuse\
go env -w CGO_CFLAGS=-IC:/WinFsp/inc/fuse
go build -ldflags="-s -w" -o juicefs.exe .
关键操作
1. 格式化文件系统
# 基本格式
juicefs format [options] META-URL NAME
# 示例 1:使用 SQLite(本地测试,最简单)
juicefs format sqlite3://myjfs.db myjfs
# 示例 2:使用 Redis + S3
juicefs format redis://localhost myjfs \
--storage=s3 \
--bucket=https://mybucket.s3.us-east-2.amazonaws.com
# 示例 3:使用 MySQL(带密码)
META_PASSWORD=mypassword juicefs format \
mysql://jfs:@(127.0.0.1:3306)/juicefs myjfs
# 示例 4:开启配额
juicefs format sqlite3://myjfs.db myjfs --inodes=1000000 --capacity=102400
# 示例 5:关闭回收站
juicefs format sqlite3://myjfs.db myjfs --trash-days=0
# 示例 6:开启压缩
juicefs format sqlite3://myjfs.db myjfs --compress=zstd
# 示例 7:开启加密
juicefs format sqlite3://myjfs.db myjfs --encrypt-rsa-key=/path/to/private.pem
# 示例 8:多 bucket 分片
juicefs format sqlite3://myjfs.db myjfs --storage=s3 --bucket=s3://bucket-prefix --shards=4
2. 挂载文件系统
# 基本格式
juicefs mount [options] META-URL MOUNTPOINT
# 前台挂载(用于调试)
juicefs format sqlite3://myjfs.db myjfs
juicefs mount sqlite3://myjfs.db /mnt/jfs
# 后台挂载(生产环境推荐)
juicefs mount redis://localhost /mnt/jfs -d
# 带密码的 Redis 后台挂载(更安全)
META_PASSWORD=mypassword juicefs mount redis://localhost /mnt/jfs -d
# 开启写缓存(提升小文件写入速度)
juicefs mount redis://localhost /mnt/jfs -d --writeback
# 只读模式
juicefs mount redis://localhost /mnt/jfs -d --read-only
# 挂载子目录
juicefs mount redis://localhost /mnt/jfs --subdir /dir/in/jfs
# Windows 挂载
juicefs mount sqlite3://myjfs.db Z:
# 关闭元数据自动备份
juicefs mount redis://localhost /mnt/jfs --backup-meta 0
# 开机自动挂载(写入 /etc/fstab)
# 方法一:手动添加 fstab 条目
echo "redis://localhost /mnt/jfs juicefs _netdev,mode=0755 0 0" | sudo tee -a /etc/fstab
# 方法二:使用 --update-fstab 选项自动添加
juicefs mount redis://localhost /mnt/jfs -d --update-fstab
3. 查看状态
# 查看文件系统状态
juicefs status redis://localhost
# 查看指定会话详情
juicefs status redis://localhost --session 1
# 查看更多统计信息
juicefs status redis://localhost --more
4. 修改配置
# 查看当前配置
juicefs config redis://localhost
# 修改配额
juicefs config redis://localhost --inodes 10000000 --capacity 1048576
# 修改回收站保留天数
juicefs config redis://localhost --trash-days 7
# 限制客户端版本
juicefs config redis://localhost --min-client-version 1.0.0
5. 垃圾回收
# 只检查(不修改)
juicefs gc redis://localhost
# 触发所有 slices 的碎片合并
juicefs gc redis://localhost --compact
# 删除泄漏的对象
juicefs gc redis://localhost --delete
# 同时合并碎片和删除泄漏对象
juicefs gc redis://localhost --compact --delete
# 指定并发线程数
juicefs gc redis://localhost --compact --delete --threads=20
6. 数据同步
# 在 JuiceFS 与对象存储之间同步
juicefs sync /mnt/jfs/data/ s3://my-bucket/backup/
# 从对象存储迁移数据到 JuiceFS
juicefs sync s3://source-bucket/ /mnt/jfs/data/
7. Kubernetes 中使用
# 安装 JuiceFS CSI Driver
helm repo add juicefs-csi-driver https://juicedata.github.io/charts/
helm repo update
helm install juicefs-csi-driver juicefs-csi-driver/juicefs-csi-driver
# 创建 Secret
kubectl create secret generic juicefs-secret \
--from-literal=metaurl="redis://localhost" \
--from-literal=storage="s3" \
--from-literal=bucket="https://mybucket.s3.us-east-2.amazonaws.com" \
--from-literal=access-key="$ACCESS_KEY" \
--from-literal=secret-key="$SECRET_KEY"
# 创建 PersistentVolume 和 PersistentVolumeClaim
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: juicefs-pv
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
csi:
driver: csi.juicefs.com
volumeHandle: juicefs-volume-id
volumeAttributes:
secretName: juicefs-secret
juicefsName: myjfs
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: juicefs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
volumeName: juicefs-pv
EOF
8. S3 Gateway
# 启动 S3 Gateway
juicefs gateway redis://localhost localhost:8010
# 使用 AWS CLI 访问
aws --endpoint-url http://localhost:8010 s3 ls s3://myjfs/
9. 基准测试
# 运行内置基准测试
juicefs bench /mnt/jfs
# 使用 fio 进行详细测试(参考 https://juicefs.com/docs/zh/community/fio )
fio --name=juicefs-test --directory=/mnt/jfs --rw=randread --bs=4k --size=1G --numjobs=1
4 行业案例
CASE Lance 智驾实践 | 卓驭:百 PB 级智驾数据存储架构演进 | 2026.09
-
Lance 智驾实践 | 卓驭:百 PB 级智驾数据存储架构演进 - Weixin/LanceDB 2026.09.16
-
卓驭起步于 2016 年,致力于成为国际一流的移动物理 AI 公司。依托独有的原生多模态基础模型和生成式 AI 技术,打造可高效适配多场景的统一移动智能技术底座,不仅为车企提供开放、可定制、量产导向的智能辅助驾驶(涵盖 L2 及以上)解决方案,更致力于为不同场景下的自主移动机器人提供底层技术,实现从地面到近地空间的全域智能移动生态赋能。

-
随着研发规模扩大,训练和推理算力逐步走向多数据中心、混合云,数据规模和访问需求也持续增长。计算资源可以按需调度,但任务启动仍可能受挂载状态、数据回源和模型加载影响。如何让数据及时就绪、减少算力等待,成为存储架构演进的重要目标。
-
卓驭基于
JuiceFS构建统一数据底座(内部迭代版本名为 ZBoost),通过统一访问、多存储池和共享缓存,支撑数据接入、容量扩展与热点复用,再结合主动预热和读取优化,加快数据交付。
目前,线上集群已承载百 PB 级数据,在线读取能力达到百 GB/s 量级。
本章节将围绕架构演进与生产实践展开。
智驾数据闭环:容量持续增长,数据反复消费
- 智能辅助驾驶的研发围绕【数据闭环】展开:路采车和量产车回传的数据经过筛选、标注,进入模型训练,再经过评测与发布;新问题和新数据又进入下一轮迭代。
在这个过程中,数据在每个环节的就绪速度,直接影响算力是否需要等待,也影响研发效率。
- 从存储角度看,【智驾研发】是一条数据密集型链路,【多模态数据】持续回流,并被不同研发任务反复消费。
量产车和路采车回传的数据,加上仿真产出的数据,首先进入共享的多模态数据存储,再由筛选、标注、模型训练、仿真评测和个人研发环境等【下游任务】使用。

智驾研发中的多模态数据流转与消费
- 随着【数据规模】和【迭代频次】增长,存储需要同时支撑【持续扩容】与【高效读取】,才能及时向【下游任务】交付数据。
原有架构中的访问、运维与扩展耦合
- 引入 JuiceFS 之前,我们同时使用 S3 接口和文件访问,多种入口并存,存储配置分散在业务侧,挂载【客户端】则由【计算侧】维护。

演进前的多种存储入口与分散配置
- 由此我们归纳出三类核心痛点:
• 挂载与调度耦合:任务启动依赖挂载客户端就绪,客户端维护延伸到计算侧,增加运维负担,并可能造成算力等待;
• 存储配置与业务耦合:Bucket、Endpoint、凭证等存储细节进入业务代码,底层资源变化需要业务配合调整;
• 容量与带宽扩展耦合:容量持续增长,热点数据反复读取,本地缓存难以跨节点复用,容量与读取带宽难以按需独立扩展。
因此,新架构需要简化业务接入和挂载维护,并支持容量与读取带宽独立扩展。
架构升级:基于 JuiceFS 构建统一数据底座
技术选型:以 S3 为核心,JuiceFS 为底座
- 为兼容存量业务并支撑后续扩展,我们选择 JuiceFS 作为存储底座,主要考虑以下:
• 多协议访问:支持 S3、POSIX 等接口,兼容不同业务的接入方式。
• 容量扩展:底层依托对象存储,承载持续增长的数据。
• 缓存加速:社区版已有本地缓存能力,可作为后续读取优化的基础。
• 开源生态:社区活跃,便于结合生产需求持续改进。

JuiceFS 社区版架构图
统一访问层:应用与存储解耦
- 新架构中,业务通过内部数据平台的 SDK 访问存储。SDK 提供统一的逻辑命名空间,并处理底层存储位置与访问凭证的映射。通过 SDK 接入的业务以 S3 访问为主,减少计算侧的挂载维护;存量业务仍可使用 POSIX 接口。

基于 SDK 的统一访问层与逻辑命名空间
- 以 S3 为核心的接入方式,也方便我们在入口进行流量隔离、监控和审计。
- 统一访问层将应用与存储的变化分开,减少底层资源调整对业务接入的影响。在保持上层接口稳定的同时,我们可以继续扩展容量、增加缓存和接入外部数据。
核心能力构建
- 我们基于 JuiceFS 社区版扩展了多存储池、分布式缓存和 UFS,整体架构如下。

多存储池、分布式缓存与 UFS 的整合架构
多存储池:容量扩展与故障隔离
- 我们在 JuiceFS 单卷的数据层增加路由,根据文件大小、权重等策略,将写入分配到不同存储池。后端可以是多个 S3 Bucket,也可以是文件存储。

单卷多存储池的写入路由与容量扩展
- 这样,JuiceFS 卷与 Bucket 形成一对多关系。当某个对象存储资源达到扩展边界时,可以增加存储池承接后续写入,已有数据不必整体搬迁。多个独立存储池也有助于缩小单一资源域故障的影响范围。
分布式缓存:跨节点复用热点数据
- 初期我们使用本地缓存,节点之间无法复用缓存数据。任务调度到新节点后,如果本地没有所需数据,就需要再次回源,并在该节点保留一份副本。这既增加读取时延,也降低了缓存空间的利用率。
- 为此,我们基于社区版开发了分布式缓存能力,多个客户端可以复用共享缓存中的热点数据,对象存储始终作为权威数据源,读取流程如下。
• 客户端通过一致性哈希选择目标缓存节点。
• 缓存节点本地盘命中时,直接返回数据。
• 未命中且允许回源时,由该节点从 S3 读取数据,返回后在缓存节点保留一份。
- 客户端本地缓存仍然可用,与分布式缓存形成多级缓存架构。

分布式缓存读取机制
UFS(Under File System):外部数据接入与缓存加速
- 我们还基于社区版开发了 UFS 能力,将外部数据源纳入 JuiceFS 的命名空间。UFS 负责外部数据的统一访问和缓存加速,权威副本继续保留在原系统中。
例如,已有一批数据存放在 S3 中,希望使用 JuiceFS 的缓存加速,就可以将其映射到 JuiceFS 的某个路径下。原始数据无需迁移,业务通过映射后的路径访问即可。

通过 UFS 将外部数据源映射到统一命名空间
- 当前映射采用只读方式,支持的后端存储类型与社区版已有的后端支持保持一致。元数据可以按需加载,也可以提前预热;即使没有预先加载,访问目录时也能按需获取外部存储的目录和文件信息。
百 PB 级集群生产实践与优化:缓存编排 / 推理场景 / 训练场景 / Lance 列存储
- 我们的线上集群已承载百 PB 级数据,带宽达到百 GB/s 量级,缓存容量达到 PB 级。围绕数据准备和任务读取,我们分别优化了缓存编排、模型配送、网络传输和数据格式。
缓存编排:随回传构建与主动预热
- 我们通过 SDK 统计发现,约八成数据会在回传后的八天内被使用。
因此,我们在数据回传时异步构建分布式缓存,并根据访问规律规划缓存容量和 TTL,使业务读取尽量命中缓存。缓存到期或容量不足时,再进行回收。

热点窗口与 TTL 驱动的缓存生命周期
- 对于需要显式控制数据准备过程的任务,我们引入 Fluid 做主动编排。Dataset 描述数据集及其来源,应用可以通过对应的 Kubernetes PVC 访问数据。
- 在任务流程中,DataLoad 配合 JuiceFS Runtime 完成预热,数据 Ready 后业务再开始消费。Fluid Controller 协调资源与状态,管理从缓存构建、业务消费到缓存回收的过程。对于未接入 Fluid 编排的业务,我们也提供 API,由业务自行控制缓存预热和淘汰。

Fluid 缓存预热与生命周期编排
推理场景:大规模模型配送
在推理场景中,数据准备主要体现为模型配送:推理 Pod 需要完成模型加载后才能提供服务。之前,Pod 启动时直接从模型仓库加载模型,节点增加后,仓库需要承担大量重复读取。为此,我们将缓存放在模型仓库与推理节点之间。
引入缓存后,模型先预热到分布式缓存,再通过缓存网络分发到各推理节点的本地缓存。同一数据块的请求通过一致性哈希落到同一缓存节点,可以在这里进行 I/O 聚合,减少重复回源。
多个推理 Pod 加载同一模型时,可以通过共享缓存聚合读取请求,将模型仓库的回源数据量尽量控制在一份模型的数据量附近。在内部推理场景中,这套方案使部署速度较原有方式提升了十倍以上。

基于共享缓存的推理模型配送
训练场景:TCP 零拷贝优化
数据进入缓存后,任务仍需要通过网络持续读取。为了减少这一过程中的开销,我们针对客户端与缓存节点之间的数据链路进行了优化,先从适用范围较广的 TCP 网络入手。
普通读取路径需要通过 ReadAt 将数据从内核读到用户态缓冲区,再通过 conn.Write 写回内核发送。在服务端命中 cacheFile、且请求范围有效时,可以通过 io.CopyN → sendfile(2) 将文件数据直接送入 TCP Socket,省去这段用户态中转。

缓存命中后的 TCP 零拷贝发送路径
- 为评估优化后缓存链路的整体性能,我们进行了 1M 顺序读压测。多服务端总带宽为 1200 Gbit/s,实测随着客户端负载增加,吞吐达到约 135–138 GiB/s。吞吐在约 135 GiB/s 时,1M 请求的 P99 时延约为 2 ms;继续提高到约 138 GiB/s 时,P99 时延升至约 20–30 ms。这说明接近带宽上限时,仍需在吞吐与尾延迟之间取舍。

顺序读压测
- 在 MLPerf Storage UNet3D 吞吐型负载中,我们首先采用单客户端高密度拓扑,将 8 个 accelerator rank 的并发读取压力集中到单节点、单条 200 Gbit/s 数据入口,验证单客户端的数据供给上限。测试覆盖 H20、H100 和 B200 三档负载;其中 H100 和 B200 已触及 200G 网络及客户端读取链路上限,瓶颈由后端存储转移至客户端数据入口。下一阶段将把 UNet3D 训练负载扩展至多客户端,并结合 RDMA,进一步验证大规模多机多卡训练下的持续供数能力与加速卡利用率。

MLPerf UNet3D 理论带宽需求与实测结果
Lance 列存储:从数据格式层面减少 I/O
- 除了提高存储链路的吞吐,我们也通过调整数据格式,减少业务实际需要读取的数据量和 I/O 次数。
- 以标注数据为例,同一个资产可能对应多个 JSON 文件,之前会将它们打成 tar 包存储。下游处理时仍需要逐帧解析 JSON,进行重复序列化和格式转换,产生大量小 I/O。
- 我们将标注数据切换为 Lance,把下游常用的 JSON 字段展开为列。数据通过 Arrow Batch 在内存中传递,批量写入 Lance Table,下游按需选择列并批量读取,减少无关字段读取、逐帧 JSON 中转和重复序列化。

- 不同流水线的收益有所差异:I/O 耗时下降约 20%–90%,IOPS 需求下降约 90%,带宽消耗下降 60% 以上,大幅降低了业务负载对存储资源的需求。
Lance 与 JuiceFS 结合预热
- 按列读取也为预热提供了更精确的范围。我们通过 Lance Manifest 等布局元信息定位所选列的物理字节区间,再映射到相交的 JuiceFS 数据块,只预热相关块,减少无关数据读取。

Lance 列到 JuiceFS 预热数据块的映射
- 相关能力已合并至 JuiceFS 社区版:按字节范围预热(PR #7398[1]),以及独立的 Lance 数据集解析工具(PR #7399[2])。两者配合,可根据指定的数据集版本和列,生成文件及字节范围列表,用于按需预热。
总结
- 回顾这次实践,我们以 JuiceFS 为统一数据底座,沿三条路径逐步演进:
- 稳定入口:通过统一访问层屏蔽底层存储差异,使存储扩容和部署调整尽量不影响业务接入。
- 共享热点:通过分布式缓存跨节点复用数据,减少任务迁移、扩容和多副本读取中的重复回源。
- 主动就绪:通过 Fluid 编排和 API 控制,让数据在业务消费前完成准备,以数据就绪状态衔接任务运行。
这三条路径共同支撑了百 PB 级集群上的数据交付,百 GB 级以上的性能需求,也降低了存储运维与业务协同成本。目前,我们仍在持续优化缓存编排、网络传输和数据格式,让数据更快就绪、减少算力等待,为智驾研发提供更稳定的存储底座。
推荐文献
- [1] PR #7398: https://github.com/juicedata/juicefs/pull/7398
- [2] PR #7399: https://github.com/juicedata/juicefs/pull/7399
CASE 从 CephFS 到 JuiceFS:同程旅行亿级文件存储平台构建之路 | 2024.12
- 从 CephFS 到 JuiceFS:同程旅行亿级文件存储平台构建之路 - 博客园 2024.12.13
Z FAQ for JuiceFS
Q: JuiceFS 解决了 MinIO 这些对象存储的什么核心问题?(必读)*
两者定位不同,本质上是互补关系而非替代。
JuiceFS 解决的是"对象存储(含 MinIO)不能当文件系统用"这一核心痛点。
-
核心关系:MinIO 提供对象存储底层 → JuiceFS 在其之上构建 POSIX 文件系统语义层。
-
JuiceFS 解决的 MinIO 核心问题:
| MinIO 的核心问题 | JuiceFS 的解决方式 |
|---|---|
无 POSIX 文件系统语义 — MinIO 只有 S3 API(Key-Value 语义),不能 mount、不能随机写、无目录树、无文件锁,传统应用程序无法直接使用 |
提供完全 POSIX 兼容的 FUSE 挂载,通过 8813 项 pjdfstest 测试,现有应用零修改即可使用 |
| 无强一致性共享读写 — S3 是最终一致性,多客户端同时读写同一数据行为不可预测 | 提供 close-to-open 强一致性,支持数千客户端同时读写,修改在所有节点立即可见 |
| 无文件锁 — 对象存储不存在 flock/fcntl 语义,并发写入同一文件无法协调 | 支持 BSD locks (flock) 和 POSIX record locks (fcntl) |
无目录树结构 — 只有 flat bucket/key 命名空间,ls/rename/mkdir 等操作语义不完整 |
在元数据引擎中维护完整的 inode 目录树,支持原子 rename、mkdir、stat 等 |
| 元数据查询能力弱 — 对象的"元数据"只有 Key+自定义标签,无法做高效的目录遍历、文件属性查询 | 独立元数据引擎(Redis/MySQL/TiKV),元数据访问延迟 1-3ms,远低于对象存储的 20-100ms |
| 大文件随机写性能差 — S3 不支持覆盖写,修改文件需重新上传整个对象 | 采用 Chunk/Slice/Block 追加写机制,随机写只上传新 Block + 更新元数据,无需读-改-写整个对象 |
| 无多级缓存 — 每次读取都需访问对象存储,延迟高 | 内置元数据缓存 + 本地数据缓存 + 预读多级缓存,预热后接近本地文件系统性能 |
| 无 Hadoop/HDFS 兼容 — 大数据生态无法直接使用 S3 作为 HDFS 替代 | 提供 Hadoop Java SDK,完整兼容 HDFS 语义,可直接替代 |
| 无配额/回收站/ACL — 纯对象存储缺少企业级文件管理能力 | 支持目录级配额、回收站、POSIX ACL、Apache Ranger 集成 |
| 协议单一 — 仅 S3 API 一种接入方式 | 支持 FUSE、Hadoop SDK、K8s CSI、S3 Gateway、WebDAV、Python SDK 等多协议接入 |
总结:MinIO 解决了"【存】"的问题(廉价海量对象存储),JuiceFS 解决了"【用】"的问题(让对象存储具备完整文件系统语义、强一致性、多协议接入和高性能缓存)。两者常组合使用——MinIO 作为 JuiceFS 的数据存储后端。

Q: JuiceFS vs. Iceberg / Paimon(湖仓格式)?(必读)
- 两者完全不在同一层,不是竞品,而是互补关系。
本质区别
| 维度 | JuiceFS | Iceberg / Paimon |
|---|---|---|
| 本质层 | 存储基础设施 — POSIX 文件系统 | 数据湖表格格式(Table Format) — 在文件之上的元数据管理层 |
| 提供什么 | 目录树、文件读写、POSIX 语义、文件锁 | 表 schema、分区、ACID 事务、时间旅行、快照 |
| 数据粒度 | 无结构的字节流(文件) | 结构化的行列数据(Parquet/ORC 文件 + 元数据) |
| 一致性模型 | close-to-open 文件级一致性 | 表级 ACID 事务(MVCC + 快照隔离) |
| 核心能力 | mount、读写文件、缓存、配额、回收站 | schema 演进、分区演进、upsert/merge、增量读取 |
| 使用者 | 应用程序、容器、Hadoop、AI 框架 | Spark、Flink、Trino、StarRocks 等计算引擎 |
| 元数据存储 | Redis/MySQL/TiKV(文件元数据) | Hive Metastore / 文件系统目录(表元数据) |
| 开源协议 | Apache 2.0 | Apache 2.0 |
一句话:JuiceFS 管的是"文件怎么存",Iceberg/Paimon 管的是"表怎么管"。前者是底层存储,后者是建在文件之上的表格式层。
可以结合使用吗?——可以,且天然互补
典型架构:
计算引擎 (Spark / Flink / Trino)
│
├── 读写表元数据 ──→ Hive Metastore(表 schema、分区信息)
│
└── 读写数据文件 ──→ JuiceFS(挂载为目录,FUSE/CSI)
│
├── 数据层 → 对象存储 (S3/MinIO/OSS)
└── 元数据层 → Redis/MySQL/TiKV
具体做法
Iceberg/Paimon 的表数据文件(Parquet/ORC)和元数据文件本身就是普通文件,存储路径只需指向 JuiceFS 挂载点即可:
-- Spark 中创建 Iceberg 表,location 指向 JuiceFS 挂载目录
CREATE TABLE iceberg_catalog.my_db.my_table (
id BIGINT,
data STRING
) USING iceberg
LOCATION '/mnt/juicefs/warehouse/my_table';
-- Paimon 同理
CREATE TABLE paimon_catalog.my_db.my_table (
pk INT,
v STRING,
PRIMARY KEY (pk) NOT ENFORCED
) WITH (
'path' = '/mnt/juicefs/warehouse/my_table'
);
结合后的收益
| 痛点 | 单独用 Iceberg/Paimon | 结合 JuiceFS |
|---|---|---|
| 小文件多 | Iceberg/Paimon 产生大量小文件,对象存储 listing 慢 | JuiceFS 元数据引擎做目录索引,listing 性能远超直接访问对象存储 |
| 元数据延迟 | 直接读写对象存储,每次 list 目录延迟 20-100ms | JuiceFS 元数据缓存 + 数据缓存,元数据延迟降至 1-3ms |
| 计算引擎访问 | 需要 S3A/Hadoop 配置,性能受限于对象存储 | FUSE 挂载即用,计算引擎透明访问,性能接近本地 |
| 多引擎共享 | 各引擎各自连 S3,无共享缓存 | JuiceFS 多客户端共享缓存,数据预热一次多引擎受益 |
| K8s 场景 | 需配置 S3A,容器无本地缓存 | CSI Driver 直接挂载 PV,容器内即为本地文件 |
| 非计算引擎访问 | 只能通过 SQL 引擎,无法直接 cat/cp |
FUSE 挂载后可直接用 shell 命令查看表数据文件 |
| 数据迁移/同步 | 手动操作对象存储 | juicefs sync 一键迁移,支持断点续传 |
注意事项
- 不能让 JuiceFS 和 Iceberg/Paimon 独立管理同一批文件:表格式层的元数据(manifest、snapshot)与文件系统层的元数据是不同维度的,各管各的,不会冲突
- JuiceFS 不提供表级 ACID:这是 Iceberg/Paimon 的职责,JuiceFS 只提供文件级一致性
- compaction 不冲突:Iceberg/Paimon 的表级 compaction(合并小文件)会产生新文件,JuiceFS 的 Slice compaction(合并数据碎片)是更底层的物理操作,两者独立运行
总结:JuiceFS 是 Iceberg/Paimon 的加速器和便捷访问层,三者叠加 = 对象存储成本 + 文件系统性能 + 表格式 ACID 能力。
Q: 怎么升级 JuiceFS 客户端?
首先卸载(umount)JuiceFS 文件系统,然后使用新版本的客户端重新挂载。建议先在测试环境验证兼容性后再升级生产环境。
Q: JuiceFS 的日志在哪里?
不同类型的客户端获取日志方式不同。FUSE 挂载的日志默认在 $HOME/.juicefs/juicefs.log(root 用户在 /var/log/juicefs.log)。也可以通过 --log=path 指定日志路径。
Q: JuiceFS 是否可以直接读取对象存储中已有的文件?
不可以。JuiceFS 有自己的数据组织格式(Chunk/Slice/Block),不是一般意义上的对象存储访问工具。如需迁移对象存储中的已有数据,请使用 juicefs sync 命令。
Q: 为什么删除文件后对象存储占用空间没有变化?
两个原因:
- 回收站:默认开启,删除的文件被放入回收站而非真正删除。可通过
juicefs config --trash-days 0关闭,或等待保留期过后自动清理。 - 异步删除:JuiceFS 是异步删除对象存储中的数据,空间变化会有延迟。可运行
juicefs gc --delete手动触发清理。
Q: JuiceFS 的性能如何?
- 元数据访问延迟:1-3 毫秒(取决于网络往返)
- 数据访问延迟:20-100 毫秒(取决于对象存储)
- 顺序读写吞吐量:50 MiB/s 至 2800 MiB/s(取决于网络带宽和压缩比)
- 缓存预热后,访问延迟和吞吐量接近单机文件系统性能
Q: JuiceFS 支持随机读写吗?
支持,包括通过 mmap 等进行的随机读写。随机写时,要覆盖的数据块的元数据被标记为旧数据,新数据块上传到对象存储并更新元数据。读取时根据最新元数据从新数据块读取。建议如需更好的随机读性能,关闭压缩(--compress none)。
Q: 怎么快速拷贝大量小文件到 JuiceFS?
挂载时加上 --writeback 选项,数据先写入本地缓存再异步上传,比直接上传快很多倍。
Q: JuiceFS 支持分布式缓存吗?
企业版支持分布式缓存。社区版仅支持单节点本地缓存。
Q: JuiceFS 目前有哪些 SDK?
- Hadoop Java SDK(官方维护):高度兼容 HDFS 接口
- Python SDK(社区维护 → v1.3 起官方支持):原生实现 fsspec,便于接入 Ray 等框架
Q: 一个文件系统可以绑定多个不同的对象存储吗?
不支持。但可以在创建时关联同一个对象存储的多个 bucket(通过 --shards 选项),解决单个 bucket 对象数量限制问题。
Q: JuiceFS 支持使用对象存储中的某个目录作为 --bucket 的值吗?
到 v1.0 为止不支持该功能。
Q: 为什么同名用户在不同主机上权限不同?
虽然用户名相同,但各主机上的 UID/GID 可能不同。使用 id 命令查看具体 UID/GID,并参考「多主机间同步账户」文档解决。
Q: JuiceFS 的异步删除流程是怎样的?
- 未开启回收站:文件被检查是否正在使用 → 是则标记
sustained(等待关闭)→ 否则标记delfile并放入删除队列 - 开启回收站:文件移动到回收站目录(按小时创建子目录)→ 后台任务根据保留天数清理过期文件 → 标记
delfile并放入删除队列 - 删除队列处理:查找文件所有 Chunk 并删除 → 减少 Slice 引用计数 → refs 降为 0 的 Slice 成为 Pending Deleted → 后台清理对象存储中的数据片段
Q: 为什么文件系统数据量与对象存储占用空间存在差异?
- 随机写产生碎片,对象存储占用 ≥ 实际大小(可通过
juicefs gc --compact --delete清理) - 回收站保留的文件未真正删除
- 碎片合并后旧碎片仍在回收站中保留
- 开启压缩后对象存储占用可能 < 实际大小
- 对象存储可能有最小计量单位(如 OSS 低频存储最小 64KB)
Y 推荐文献
- JuiceFS 官方文档中心 — 最全面的参考资料,涵盖安装、架构、运维、最佳实践
- JuiceFS 技术架构详解 — 深入理解 Chunk/Slice/Block 设计与存储原理
- JuiceFS 内部实现详解 — 元数据结构、数据流、垃圾回收机制的源码级分析
- JuiceFS 与 CephFS 对比 — 架构差异与选型参考
- JuiceFS 命令参考 — 所有命令的完整参数说明
- JuiceFS 2025 年度回顾 — 社区发展数据、企业版规模突破、技术方向
- JuiceFS 性能基准测试 (fio) — 使用 fio 进行性能测试的方法和结果
- JuiceFS 客户端缓存指南 — 多级缓存机制详解与调优
- JuiceFS CSI Driver 文档 — Kubernetes 环境下的使用指南
- JuiceFS GitHub Discussions — 社区问答与最佳实践分享
- DeepWiki: Mount and Format Commands — format 和 mount 命令的源码级解读
X 参考文献
- JuiceFS 官网
- JuiceFS - GitHub
- JuiceFS 文档中心
- JuiceFS 技术架构
- JuiceFS 内部实现
- JuiceFS 与 CephFS 对比
- JuiceFS 安装指南
- JuiceFS 命令参考
- JuiceFS FAQ
- JuiceFS 2025 年度回顾 - SegmentFault
- JuiceFS v1.4.0 Release - GitHub
- JuiceFS Quick Start - GitHub
- Star History - juicefs
- OSSInsight - juicefs
- 开源对象存储 2026 横评 - 知乎
- 海量小文件存储选型指南 - 百度开发者
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号