JuiceFS 新手必知 24 问

2022-08-10
执剑

JuiceFS 是一个创新性的软件产品,很多初次尝试的小伙伴对产品和用法感到很多疑惑,所以为了帮助大家快速理解并上手 JuiceFS,我们整理了24个关于 JuiceFS 经典的问题答案,相信经过这 24 问,大家对 JuiceFS 会有更清晰的认识,使用上也会更加得心应手。

1. JuiceFS 的基本能力是什么

JuiceFS 是一款面向云原生设计的高性能共享文件系统,在 Apache 2.0 开源协议下发布。提供完备的 POSIX 兼容性,可将几乎所有对象存储接入本地作为海量本地磁盘使用,亦可同时在跨平台、跨地区的不同主机上挂载读写。

2. JuiceFS 的性能如何

JuiceFS 是一个分布式文件系统,元数据访问的延时取决于挂载点到服务端之间 1 到 2 个网络来回(通常 1-3 ms),数据访问的延时取决于对象存储的延时 (通常 20-100 ms)。顺序读写的吞吐量可以到 50MiB/s 至 2800MiB/s(查看 fio 测试结果),取决于网络带宽以及数据是否容易被压缩。

JuiceFS 内置多级缓存(主动失效),一旦缓存预热好,访问的延时和吞吐量非常接近单机文件系统的性能(FUSE 会带来少量的开销)。

3. JuiceFS 的运行的必要条件

在运行前,需要准备元数据引擎与对象存储, 元数据引擎中存储的是文件的名称,大小,修改时间等元数据,而对象存储中存储的是文件的内容。

元数据引擎当前支持:Redis,TiKV,MySQL,PostgreSQL等,当前元数据引擎的支持清单与具体配置参考如何设置元数据引擎文档

对象存储支持的就更多了,基本常见的对象存储都支持了,比如 AWS S3,阿里云 OSS,华为云 OBS,腾讯云 COS等等,另外为了方便测试,还特别支持本地磁盘作为对象存储。当前对象存储的支持清单与具体配置参考如何设置对象存储文档

4. JuiceFS 使用的步骤

使用步骤非常简单,分两步,第一步格式化,第二步挂载到本地。下面就是使用 JuiceFS 与 Redis 将阿里云 OSS 挂载到本地的示例:

# 1. 格式化一个文件系统
juicefs format \
--storage oss \
--bucket https://zhijian-dev.oss-cn-hangzhou.aliyuncs.com \
--access-key xxxx \ 
--secret-key xxxx \
redis://localhost:6379/1 \
test1 

# 2. 后台挂载文件系统到 /tmp/jfs 目录
juicefs mount -d redis://localhost:6379/1 /tmp/jfs

5. 最快体验 JuiceFS 的方式

我本地没有 Redis,也没有对象存储,能否体验 JuiceFS?当然可以,拉起 JuiceFS 服务需要元数据引擎以及对象存储两个组件,但在这两个组件我们可以使用最简单的,比如元数据引擎用 SQLite这个嵌入式数据库,而对象存储使用本地磁盘(format 时的 --bucket 参数不填即为默认参数,默认为使用本地磁盘作为对象存储,root 用户默认存储路径为 /var/jfs,普通用户默认存储路径为 ~/.juicefs/local)。这样就可以只需要 JuiceFS 二进制不需要任何外部组件就能体验 JuiceFS 产品了。

# 1. 使用 sqlite 作为元数据引擎格式化文件系统 
juicefs format "sqlite3://my-jfs.db" test1

# 2. 后台挂载文件系统到 /tmp/jfs 目录
juicefs mount -d sqlite3://my-jfs.db /tmp/jfs

6. 可以用 root 以外的用户挂载吗

可以,JuiceFS 可以由任何用户挂载。默认的缓存目录是 $HOME/.juicefs/cache(macOS)或者 /var/jfsCache(Linux),请确保该用户对这个目录有写权限,或者切换到其它有权限的目录。请查看「客户端读缓存」了解更多信息。

7. JuiceFS 对 POSIX 协议的兼容性如何

JuiceFS 借助 PjdfstestLTP 来验证其对 POSIX 的兼容性,最终测试结果为通过了 pjdfstest 中的所有测试用例以及 LTP 中的绝大部分用例。

8. JuiceFS 除了普通挂载外还支持哪些方式访问数据

除了普通挂载外,还支持以下几种方式:

9. 支持哨兵或者集群模式的 Redis 作为 JuiceFS 的元数据引擎吗?

支持,另外这里还有一篇 Redis 作为 JuiceFS 元数据引擎的最佳实践文章可供参考。

10. 如何测试 JuiceFS 的性能

将 JuiceFS Mount 到本地目录后,对这个目录执行 JuiceFS bench 命令。JuiceFS bench 命令会在该目录上进行大文件与小文件读写测试。比如:

# /tmp/jfs 是 JuiceFS 挂载在本地的目录
$ juicefs bench /tmp/jfs
Cleaning kernel cache, may ask for root privilege...
Password:
  Write big blocks count: 1024 / 1024 [==============================================================]  done
   Read big blocks count: 1024 / 1024 [==============================================================]  done
Write small blocks count: 100 / 100 [==============================================================]  done
 Read small blocks count: 100 / 100 [==============================================================]  done
  Stat small files count: 100 / 100 [==============================================================]  done
Benchmark finished!
BlockSize: 1 MiB, BigFileSize: 1024 MiB, SmallFileSize: 128 KiB, SmallFileCount: 100, NumThreads: 1
+------------------+-----------------+--------------+
|       ITEM       |      VALUE      |     COST     |
+------------------+-----------------+--------------+
|   Write big file |   1236.96 MiB/s |  0.83 s/file |
|    Read big file |   2962.88 MiB/s |  0.35 s/file |
| Write small file |  2277.4 files/s | 0.44 ms/file |
|  Read small file |  2753.0 files/s | 0.36 ms/file |
|        Stat file | 16603.3 files/s | 0.06 ms/file |
+------------------+-----------------+--------------+

juicefs bench命令还可以作为 mount 后的简单的测试方便快速判断 JuiceFS 服务是否正常。更多关于 JuiceFS 性能测试相关的问题可以看这篇性能评估指南文档

11. 如何测试对象存储的兼容性与性能

对象存储是 JuiceFS 的重要的组件,对象存储的正确性与性能直接影响 JuiceFS 服务的正确性与性能,所以当 JuiceFS 出现问题的时候可以尝试先排除对象存储出问题的可能性。为了方便大家测试,我们内置了juicefs objbench命令,该命令可以快速测试对象存储的正确性以及其性能。示例:

$ juicefs objbench --storage minio  http://127.0.0.1:9000/testbucket --access-key admin --secret-key admin123
Start Functional Testing ...
+----------+---------------------+-------------+
| CATEGORY |         TEST        |    RESULT   |
+----------+---------------------+-------------+
|    basic |     create a bucket |        pass |
|    basic |       put an object |        pass |
|    basic |       get an object |        pass |
|    basic |       get non-exist |        pass |
|    basic |  get partial object |        pass |
|    basic |      head an object |        pass |
|    basic |    delete an object |        pass |
|    basic |    delete non-exist |        pass |
|    basic |        list objects |        pass |
|     sync |    put a big object |        pass |
|     sync | put an empty object |        pass |
|     sync |    multipart upload |        pass |
|     sync |  change owner/group | not support |
|     sync |   change permission | not support |
|     sync |        change mtime | not support |
+----------+---------------------+-------------+

Start Performance Testing ...
put small objects count: 100 / 100 [==============================================================]  done
get small objects count: 100 / 100 [==============================================================]  done
   upload objects count: 256 / 256 [==============================================================]  done
 download objects count: 256 / 256 [==============================================================]  done
     list objects count: 100 / 100 [==============================================================]  done
     head objects count: 100 / 100 [==============================================================]  done
   delete objects count: 100 / 100 [==============================================================]  done
Benchmark finished! block-size: 4096 KiB, big-object-size: 1024 MiB, small-object-size: 128 KiB, small-objects: 100, NumThreads: 4
+--------------------+--------------------+-----------------+
|        ITEM        |        VALUE       |       COST      |
+--------------------+--------------------+-----------------+
|     upload objects |        67.12 MiB/s | 59.59 ms/object |
|   download objects |       106.86 MiB/s | 37.43 ms/object |
|  put small objects |    508.2 objects/s |  1.97 ms/object |
|  get small objects |    728.0 objects/s |  1.37 ms/object |
|       list objects | 46890.01 objects/s |      2.13 ms/op |
|       head objects |   2861.2 objects/s |  0.35 ms/object |
|     delete objects |   2295.1 objects/s |  0.44 ms/object |
| change permissions |        not support |     not support |
| change owner/group |        not support |     not support |
|       update mtime |        not support |     not support |
+--------------------+--------------------+-----------------+

12. 卸载挂载点报 Resource busy -- try 'diskutil unmount' 错误

这代表挂载点下的某个文件或者目录正在被使用,无法直接 umount,可以检查(如通过 lsof 命令)是否有打开的终端正位于 JuiceFS 挂载点的某个目录,或者某个应用程序正在处理挂载点中的文件。如果有,则退出终端或应用程序后再尝试使用 juicefs umount 命令卸载文件系统。

13. 如何销毁一个文件系统

使用 juicefs destroy 命令销毁一个文件系统,该命令将会清空元数据引擎与对象存储中的相关数据。关于该命令的使用详情请参考文档

14. JuiceFS 的日志在哪里

JuiceFS 后台挂载的时候日志才会写入日志文件,前台挂载或者其他前台的命令都会将日志直接打印到终端

Mac 系统上日志文件默认是/Users/$User/.juicefs/juicefs.log

Linux 系统上日志文件默认是/var/log/juicefs.log

15. 为什么在对象存储中看不到存入 JuiceFS 的原文件

使用 JuiceFS,文件最终会被拆分成 Chunks、Slices 和 Blocks 存储在对象存储。因此,你会发现在对象存储平台的文件浏览器中找不到存入 JuiceFS 的源文件,存储桶中只有一个 chunks 目录和一堆数字编号的目录和文件。不要惊慌,这正是 JuiceFS 文件系统高性能运作的秘诀!详情参考 JuiceFS 如何存储文件

16. JuiceFS 随机写的基本原理是什么

JuiceFS 不将原始文件存入对象存储,而是将其按照某个大小(默认为 4MiB)拆分为 N 个数据块(Block)后,上传到对象存储,然后将数据块的 ID 存入元数据引擎。随机写的时候,逻辑上是要覆盖原本的内容,实际上是把要覆盖的数据块的元数据标记为旧数据,同时只上传随机写时产生的新数据块到对象存储,并将新数据块对应的元数据更新到元数据引擎中。

当读取被覆盖部分的数据时,根据最新的元数据,从随机写时上传的新数据块读取即可,同时旧数据块可能会被后台运行的垃圾回收任务自动清理。这样就将随机写的复杂度转移到读的复杂度上,。

这个只是很粗略的实现逻辑介绍,具体的读写流程非常复杂,可以研读 JuiceFS内部实现读写流程这两篇文档并结合代码一起梳理。

17. 为什么我在挂载点删除了文件,但是对象存储占用空间没有变化或者变化很小

第一个原因是你可能开起了回收站特性,为了保证数据安全回收站默认开启,删除的文件其实被放到了回收站,实际并没有被删除,所以对象存储大小不会变化。回收站的保留时间可以通过 juicefs format指定或者通过 juicefs config 修改。请参考「回收站」文档了解更多信息。

第二个原因是 JuiceFS 是异步删除对象存储中的数据,所以对象存储的空间变化会慢一点。如果你需要立即清理对象存储中需要被删除的数据,可以尝试运行 juicefs gc命令。

18. 为什么挂载点显示的大小与对象存储占用空间存在差异

通过「JuiceFS 支持随机写的实现原理是什么?」这个问题的答案可以推断出,对象存储的占用空间大部分情况下是大于等于实际大小的,尤其是短时间内进行大量的覆盖写产生许多文件碎片后。这些碎片在未触发合并与回收前其仍旧占用着对象存储的空间。不过也不必担心这些碎片一直占用空间,因为在每次读/写文件的时候都会检查并在必要的时候触发该文件相关碎片的整理工作。另外你可以通过 juicefs gc —-compact -—delete 命令手动触发合并与回收。

另外如果 JuiceFS 文件系统开启了压缩功能(默认不开启),那么对象存储上存储的对象有可能比实际文件大小更小(取决于不同类型文件的压缩比)。

如果以上因素都已经排除,请检查你使用的对象存储的存储类型是什么,云服务商可能会针对某些存储类型设置最小计量单位。例如阿里云 OSS 低频访问存储的最小计量单位是 64KB,如果单个文件小于 64KB 也会按照 64KB 计算。

19. JuiceFS S3 网关支持多用户管理等高级功能吗

JuiceFS 内置的 gateway 子命令不支持多用户管理等功能,只提供基本的 S3 Gateway 功能。如果需要使用这些高级功能,可以参考我们的这个仓库,其将 JuiceFS 作为 MinIO gateway 后端的一种实现,支持 MinIO gateway 的完整功能。

20. JuiceFS 与 XXX 的区别是什么

请查看「同类技术对比」文档了解更多信息。

21. JuiceFS 支持使用对象存储中的某个目录作为 —-bucket 选项的值吗

到 JuiceFS 1.0.0-rc3 为止,还不支持该功能。

22. JuiceFS 支持读取对象存储中已经存在的数据吗

到 JuiceFS 1.0.0-rc3 为止,还不支持该功能。

23. JuiceFS 目前支持分布式缓存吗

到 JuiceFS 1.0.0-rc3 为止,还不支持该功能

24. JuiceFS 目前有 SDK 可以使用吗

截止到 JuiceFS 1.0.0-rc3 发布,社区有两个 SDK,一个是 Juicedata 官方维护的 HDFS 接口高度兼容的 Java SDK,另一个是由社区用户维护的 Python SDK

相关博客

性能、成本与 POSIX 兼容性比较: JuiceFS vs EFS vs FSx for Lustre

2024-09-04
在本文中,我们将通过一系列测试,来评估这三种主流文件系统的性能与成本表现,帮助用户快速了解这些产品。

SeaweedFS + TiKV 部署保姆级教程

2024-07-12
在使用 JuiceFS 时,我们选择了 SeaweedFS 作为对象存储,以及 TiKV 作为元数据存储,目前在 SeaweedFS 上已经存储了近1.5PB 的数据。本文将为社区各位用户提供我们的…

极限挑战:使用 Go 打造百亿级文件系统的实践之旅

2024-02-02
本文介绍了 JuiceFS 在设计元数据引擎时所做的关键决策,并详细介绍了内存池、自主管理小块内存、压缩空闲目录以及优化小文件格式这 4 个内存优化手段。

JuiceFS 用户必备的 6 个技巧

2023-11-22
随着大数据、AI 技术的发展,越来越多的企业、团队和个人开始使用 JuiceFS,本文整理了 6 个超实用的 JuiceFS 技巧,帮助大家提升 JuiceFS 的管理效率。