
JuiceFS 常见问题深度解析异步删除、随机写、对象存储与性能调优实战指南【免费下载链接】juicefsJuiceFS is a distributed POSIX file system built on top of Redis and S3.项目地址: https://gitcode.com/GitHub_Trending/ju/juicefsJuiceFS 是一个基于 Redis或其他元数据引擎与 S3或其他对象存储构建的分布式 POSIX 文件系统。本文以官方中文 FAQ 为骨架逐一解答用户在元数据、对象存储、性能与访问方式上最常见的疑问并结合仓库源码cmd/、pkg/meta/、pkg/chunk/等剖析背后的实现原理帮助读者既“知其然”也“知其所以然”。读完本文你将能准确判断删除后空间不释放的原因、理解随机写与异步清理的完整数据流、掌握回收站与垃圾回收gc的运维手段并了解 JuiceFS 除挂载之外的多种访问方式。通用问题架构认知与日常运维怎么升级 JuiceFS 客户端升级客户端非常简单先卸载 JuiceFS 文件系统juicefs umount然后使用新版本客户端重新挂载即可。由于客户端是用户态进程数据本身存储在对象存储与元数据引擎中升级不会影响已有数据。JuiceFS 的日志在哪里不同类型的 JuiceFS 客户端获取日志的方式不同挂载FUSE客户端的日志在挂载后可通过juicefs stats、juicefs debug或指定的日志目录查看其他接入方式如 Kubernetes CSI、Hadoop SDK、S3 网关的日志位置也各有差异详情可参考「客户端日志」文档。JuiceFS 是否可以直接读取对象存储中已有的文件不可以。JuiceFS 是一个用户态文件系统虽然它通常使用对象存储作为数据存储层但它并不是一般意义上的对象存储访问工具。JuiceFS 会把文件按固定大小切分成数据块Block上传到对象存储并将数据块的索引与文件属性存入元数据引擎因此对象存储 Bucket 中不会出现原始文件。这一设计细节可参考「技术架构」文档。如果希望把对象存储 Bucket 中已有数据迁移进 JuiceFS可以使用juicefs sync命令完成双向同步。如何将多台服务器组合成一个 JuiceFS 文件系统来使用不可以。虽然 JuiceFS 支持使用本地磁盘或 SFTP 作为底层存储但它并不干预底层存储的逻辑结构管理。如果希望把多台服务器的存储空间整合起来可以考虑先用 MinIO 或 Ceph 创建对象存储集群然后在其之上创建 JuiceFS 文件系统。元数据相关问题Redis 引擎的能力边界支持哨兵Sentinel或者集群Cluster模式的 Redis 作为元数据引擎吗支持。JuiceFS 的元数据引擎采用多引擎设计已支持 Redis、TiKV、MySQL/MariaDB、PostgreSQL、SQLite 等其中 Redis 支持 Standalone、Sentinel、Cluster 三种部署模式可在元数据引擎的配置说明中找到对应的连接串写法。此外官方还提供了一篇 Redis 作为 JuiceFS 元数据引擎的最佳实践文档涵盖持久化、高可用等生产级配置建议。对象存储相关问题容量、删除与数据布局为什么不支持某个对象存储JuiceFS 已经支持了绝大部分对象存储包括各大公有云的对象存储以及 Ceph、MinIO 等私有化对象存储完整列表见「对象存储配置指南」。如果目标对象存储与 S3 协议兼容也可以直接当成 S3 使用否则可以在社区提交 issue 请求增加支持。为什么我在挂载点删除了文件但对象存储占用空间没有变化或者变化很小这是用户最常遇到的困惑通常有两个原因第一个原因是回收站特性默认开启。为了保证数据安全JuiceFS 默认开启回收站删除的文件实际被移动到了文件系统根目录下的.trash目录数据并未真正删除因此对象存储大小不会立即变化。回收站的保留时间可以通过juicefs format指定也可以通过juicefs config随时修改。例如# 初始化新的文件系统时指定保留 7 天 juicefs format META-URL myjfs --trash-days7 # 修改已有文件系统的保留时长 juicefs config META-URL --trash-days7 # 设置为 0 以禁用回收站 juicefs config META-URL --trash-days0在源码层面--trash-days由 cmd/format.go 中的formatManagementFlags定义默认值为1即默认保留 1 天cmd/config.go 则实现了对已有文件系统该参数的在线修改。详细机制请参考「回收站」文档。第二个原因是异步删除。JuiceFS 采用异步方式删除对象存储中的数据文件删除后chunk 数据由后台任务逐步清理所以对象存储空间变化会慢一些。如果希望立即清理可删除的数据可以运行juicefs gc命令# 只扫描检查不做任何写入性变更 juicefs gc redis://localhost # 触发所有 Slice 的碎片合并 juicefs gc redis://localhost --compact # 删除泄漏对象、延迟删除的 Slice 或文件 juicefs gc redis://localhost --delete # 数据量很大时使用外部排序降低内存占用 juicefs gc redis://localhost --external-sort-dir /tmp/gc-work从 cmd/gc.go 可以看到gc命令提供--compact、--delete、--threads默认 10与--external-sort-dir等选项其核心动作包括CleanupTrashBefore按回收站过期时间清理、ScanDeletedObject扫描延迟删除的对象、CompactAll全量碎片合并与CleanupSlices清理引用计数为零的 Slice。关于 JuiceFS 的异步删除具体流程是怎样的异步删除是 JuiceFS 的核心机制之一其完整流程分为三个阶段未开启回收站时系统检查文件是否正被其他程序使用如果文件正在被使用会标记为“暂缓删除sustained”等程序关闭文件后再处理如果文件没有被使用会标记为“待删除delfile”并尝试将其放入“删除队列maxDeleting”。开启回收站时系统会在回收站中按照当前时间精确到小时创建子目录如2024-01-15-14待删除文件被移动到对应时间目录中此时所有 chunk 和 slice 数据均保持完整仅元数据中的父目录指向发生变化文件名会被重新编码形如[parent inode]-[file inode]-[file name]以避免冲突后台任务根据保留天数清理过期文件从最老的目录开始逐个清理方法同样是打上“待删除delfile”标记并放入删除队列maxDeleting。删除队列处理流程异步清理查找文件对应的所有 chunk 并删除删除 chunk 时会减少其 slice 的引用计数当 slice 的引用计数减为零成为“Pending Deleted Slices”待删除 Slice由后台任务清理对象存储中的这些数据片段。在元数据引擎的实现中pkg/meta/redis.go中定义了sustained: session$sid - [$inode]暂缓删除集合与delfiles - [$inode:$length - seconds]待删除文件的有序集合两类数据结构删除时先把 inode 写入对应集合再由后台任务消费。sustained与delfiles的完整键定义可在 pkg/meta/redis.go 中查看。关于该流程还有几个重要补充删除队列是有容量限制的。如果同时删除的文件过多队列满后删除请求会先返回然后由一个每小时工作一次的后台清理任务继续清理它查找所有标记为待删除delfile的文件并清理清理方法与删除队列中的文件一致。如果配置了NoBGJob即挂载时指定--no-bgjob每小时间隔的后台定时清理任务和回收站清理任务都会被禁用删除文件后需要手动进入回收站进一步清理。一种特殊情况当你手动直接删除回收站里的文件时可以确保以同步方式插入删除队列相对较快地回收对象存储空间但后续清理 chunk 的动作仍然是异步的。关于 slice 引用计数删除 chunk 和碎片整理compact会减少相关 slice 的引用计数而clone和copyFileRange会增加相关 slice 的引用计数这正是后文“数据量不一致”问题的重要来源。为什么文件系统数据量与对象存储占用空间存在差异这是一个多因素共同作用的结果主要有以下几点随机写产生文件碎片JuiceFS 的随机写会把被覆盖的旧数据块标记为失效仅上传新数据块因此对象存储的占用空间在大部分情况下大于等于实际大小。尤其是短时间内大量覆盖写会产生许多碎片这些碎片仍占用着对象存储空间。不过不必担心每次读写文件时都会检查碎片化情况并在客户端后台任务中进行相关碎片的整理合并。你也可以通过juicefs gc --compact --delete命令手动触发合并与回收。回收站保留如果开启了回收站功能被删除的文件不会立刻清理而是在回收站内保留指定时间后才被清理删除。碎片也进回收站碎片被合并以后失效的旧碎片也会在回收站中进行保留但对用户不可见过期时间遵循回收站的设置。可通过juicefs status META-URL --more观测其规模输出中的Trash Slices与Pending Deleted Slices即对应这部分数据。如需清理可参考「回收站和文件碎片」。压缩功能如果文件系统开启了压缩功能即format命令的--compress参数默认不开启那么对象存储上存储的对象有可能比实际文件大小更小具体取决于不同类型文件的压缩比。对象存储的最小计量单位根据所使用对象存储的存储类型不同云服务商可能会设置最小计量单位。例如阿里云 OSS 低频访问存储的最小计量单位是 64KB单个文件小于 64KB 也会按 64KB 计算。自建对象存储的存储级别对于自建对象存储例如 MinIO实际占用大小还受其存储级别如纠删码、副本数设置的影响。关于 bucket 的几个边界问题--bucket选项是否支持对象存储中的某个目录到 JuiceFS 1.0 为止还不支持该功能。是否支持访问对象存储中已经存在的数据到 JuiceFS 1.0 为止还不支持该功能这也是 FAQ 中“无法直接读取已有文件”的延伸结论。一个文件系统可以绑定多个不同的对象存储吗比如同时用 S3、GCS 和 OSS不支持。但在创建文件系统时可以设定关联同一个对象存储服务的多个 bucket从而解决单个 bucket 对象数量限制的问题例如为一个文件系统关联多个 S3 Bucket。具体请参考format命令的--shards选项 说明。性能相关问题从数字到原理JuiceFS 的性能如何JuiceFS 是一个分布式文件系统其性能指标可以拆解为两部分元数据访问延时取决于挂载点到元数据服务之间 1 到 2 个网络来回读 1 次、写 2 次通常为 1-3 ms。数据访问延时取决于对象存储的延时通常为 20-100 ms。顺序读写吞吐量可以达到 50MiB/s 至 2800MiB/s取决于网络带宽以及数据是否容易被压缩可查看 fio 测试结果。此外JuiceFS 内置多级缓存主动失效机制。一旦缓存预热好访问的延时和吞吐量会非常接近单机文件系统FUSE 会带来少量开销。JuiceFS 支持随机读写吗原理如何支持包括通过 mmap 等进行的随机读写。目前 JuiceFS 主要对顺序读写进行了大量优化对随机读写的优化也在进行中。如果追求更好的随机读性能建议关闭压缩--compress none。随机读写的原理与 JuiceFS 的存储布局紧密相关。JuiceFS 不将原始文件存入对象存储而是将其按照某个大小默认为 4MiB拆分为 N 个数据块Block上传到对象存储然后将数据块的 ID 存入元数据引擎。Chunk 与 Slice 的引用关系中标记了各个 Slice 的有效数据偏移范围细节可参考「内部实现」中的SliceRef部分。随机写的实际过程是逻辑上要覆盖原本的内容实际上把要覆盖的数据块的元数据标记为旧数据同时只上传随机写产生的新数据块到对象存储并将新数据块对应的元数据更新到元数据引擎中。当读取被覆盖部分的数据时根据最新的元数据从新数据块读取即可而旧数据块可能被后台运行的垃圾回收任务自动清理。这样就把随机写的复杂度转移到了读的复杂度上。关于 Chunk/Slice/Block 的完整数据模型文件切分为最大 64M 的 Chunk、连续写入形成 Slice、物理落盘拆分为最大 4M 的 Block可阅读「技术架构」与「读写请求处理流程」文档。怎么快速地拷贝大量小文件到 JuiceFS在挂载时加上--writeback选项它会先把数据写入本机缓存然后再异步上传到对象存储比直接上传到对象存储快很多倍# 启用 writeback 模式以可能丢失对象为代价提升性能 juicefs mount redis://localhost /mnt/jfs -d --writeback该选项在 cmd/mount.go 中被解析为Writeback配置配合--writeback-threshold-size可控制触发写回的数据量阈值。更多细节请参考「客户端写缓存」。JuiceFS 支持分布式缓存吗社区版目前不提供分布式缓存该能力属于企业版功能。访问相关问题权限、协议与 SDK为什么同名用户在主机 X 上有权限访问 JuiceFS 的文件在主机 Y 上访问该文件却没有权限虽然用户在主机 X 和主机 Y 上的用户名相同但各自对应的 UID 或 GID 可能不相同。JuiceFS 记录文件权限时使用的是数字 UID/GID 而非用户名。可以使用id命令查看用户的具体 UID 和 GID$ id alice uid1201(alice) gid500(staff) groups500(staff)阅读文档「多主机间同步账户」可以解决这个问题。另外如果确实需要以非 root 用户挂载 JuiceFS只需将缓存目录改为当前用户有写权限的路径即可默认目录为$HOME/.juicefs/cacheLinux 下为/var/jfsCache。JuiceFS 除了挂载外还支持哪些方式访问数据除了 FUSE 挂载外JuiceFS 还支持以下几种访问方式Kubernetes CSI 驱动通过 Kubernetes CSI 驱动将 JuiceFS 作为 Kubernetes 集群的存储层详情参考「JuiceFS CSI 驱动」。Hadoop Java SDK通过兼容 HDFS 接口的 Java 客户端在 Hadoop 生态中使用 JuiceFS详情参考「Hadoop 使用 JuiceFS」。S3 网关通过 S3 协议访问 JuiceFS可使用 AWS CLI、s3cmd、MinIO client 等工具详情参考「配置 JuiceFS S3 网关」。Docker Volume 插件在 Docker 中方便使用 JuiceFS 的方式详情参考「Docker 使用 JuiceFS」。WebDAV 网关通过 WebDAV 协议HTTP 之上的类 RESTful 接口访问 JuiceFS。JuiceFS S3 网关支持多用户管理等高级功能吗JuiceFS 内置的gateway命令从 1.2 版本开始支持多用户管理等高级功能。JuiceFS 目前有 SDK 可以使用吗截至 JuiceFS 1.0 发布社区有两个 SDK一个是 Juicedata 官方维护、与 HDFS 接口高度兼容的 Java SDK源码位于本仓库 sdk/java 目录包含libjfsGo 实现与srcJava 实现两部分另一个是由社区用户维护的 Python SDK。后者同时被官方架构文档列为受支持的接入方式之一Python SDK 原生实现了 fsspec便于接入 Ray 等框架详见「Python SDK」。总结围绕 JuiceFS 最常见的疑问本文梳理出一条清晰的认知主线对象存储只保存被切分的数据块元数据引擎保存文件索引删除是“元数据先行、数据异步回收”随机写通过“新数据块替换 旧数据块垃圾回收”实现回收站与碎片机制共同导致容量口径的差异。理解了这些底层机制再配合juicefs format/config、juicefs gc、juicefs status --more等命令就能在生产环境中准确诊断容量问题、主动回收空间并为不同的工作负载选择挂载选项如--writeback与访问方式CSI、Hadoop SDK、S3 网关等。【免费下载链接】juicefsJuiceFS is a distributed POSIX file system built on top of Redis and S3.项目地址: https://gitcode.com/GitHub_Trending/ju/juicefs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考