共计 3426 个字符,预计需要花费 9 分钟才能阅读完成。
对于一个由对象存储和数据库组合驱动的文件系统,缓存是本地客户端与远端服务之间高效交互的重要纽带。读写的数据能够提前或者异步载入缓存,再由客户端在后盾与远端服务交互执行异步上传或预取数据。相比间接与远端服务交互,采纳缓存技术能够大大降低存储操作的延时并进步数据吞吐量。
数据一致性
JuiceFS 提供「敞开再关上(close-to-open)」一致性保障,即当两个及以上客户端同时读写雷同的文件时,客户端 A 的批改在客户端 B 不肯定能立刻看到。然而,一旦这个文件在客户端 A 写入实现并敞开,之后在任何一个客户端从新关上该文件都能够保障能拜访到最新写入的数据,不管是否在同一个节点。
「敞开再关上」是 JuiceFS 提供的最低限度一致性保障,在某些状况下可能也不须要从新关上文件能力拜访到最新写入的数据。例如多个应用程序应用同一个 JuiceFS 客户端拜访雷同的文件(文件变更立刻可见),或者在不同节点上通过 tail -f
命令查看最新数据。
元数据缓存
JuiceFS 反对在内核和客户端内存(即 JuiceFS 过程)中缓存元数据以晋升元数据的拜访性能。
内核元数据缓存
内核中能够缓存三种元数据:属性(attribute)、文件项(entry)和 目录项(direntry),能够通过以下挂载参数管制缓存工夫:
--attr-cache value 属性缓存时长,单位秒 (默认值: 1)
--entry-cache value 文件项缓存时长,单位秒 (默认值: 1)
--dir-entry-cache value 目录项缓存时长,单位秒 (默认值: 1)
JuiceFS 默认会在内核中缓存属性、文件项和目录项,缓存时长 1 秒,以进步 lookup 和 getattr 的性能。当多个节点的客户端同时应用同一个文件系统时,内核中缓存的元数据只能通过工夫生效。也就是说,极其状况下可能呈现节点 A 批改了某个文件的元数据(如 chown
),通过节点 B 拜访未能立刻看到更新的状况。当然,等缓存过期后,所有节点最终都能看到 A 所做的批改。
客户端内存元数据缓存
留神:此个性须要应用 0.15.0 及以上版本的 JuiceFS。
JuiceFS 客户端在 open()
操作即关上一个文件时,其文件属性(attribute)会被主动缓存在客户端内存中。如果在挂载文件系统时设置了 --open-cache
选项且值大于 0,只有缓存尚未超时生效,随后执行的 getattr()
和 open()
操作会从内存缓存中立刻返回后果。
执行 read()
操作即读取一个文件时,文件的 chunk 和 slice 信息会被主动缓存在客户端内存。在缓存有效期内,再次读取 chunk 会从内存缓存中立刻返回 slice 信息。
提醒:您能够查阅「JuiceFS 如何存储文件」理解 chunk 和 slice 是什么。
默认状况下,对于一个元数据曾经被缓存在内存的文件,超过 1 小时没有被任何过程拜访,其所有元数据缓存会被主动删除。
数据缓存
JuiceFS 对数据也提供多种缓存机制来进步性能,包含内核中的页缓存和客户端所在节点的本地缓存。
内核数据缓存
留神:此个性须要应用 0.15.0 及以上版本的 JuiceFS。
对于曾经读过的文件,内核会把它的内容主动缓存下来,随后再关上该文件,如果文件没有被更新(即 mtime 没有更新),就能够间接从内核中的缓存读取该文件,从而取得最好的性能。得益于内核缓存,反复读取 JuiceFS 中雷同文件的速度会十分快,延时可低至微秒,吞吐量能够到每秒数 GiB。
JuiceFS 客户端目前还未默认启用内核的写入缓存性能,从 Linux 内核 3.15 开始,FUSE 反对「writeback-cache 模式」这意味着能够十分疾速地实现 write()
零碎调用。你能够在挂载文件系统时设置 -o writeback_cache
选项开启 writeback-cache 模式。当须要频繁写入十分小的数据(如 100 字节左右)时,倡议启用此挂载选项。
客户端读缓存
JuiceFS 客户端会依据读取模式主动预读数据放入缓存,从而进步程序读的性能。默认状况下,会在读取数据时并发预读 1 个 block 缓存在本地。本地缓存能够设置在基于机械硬盘、SSD 或内存的任意本地文件系统。
本地缓存能够在挂载文件系统时通过以下选项进行调整:
--prefetch value 并发预读 N 个块 (默认: 1)
--cache-dir value 本地缓存目录门路;应用冒号隔离多个门路 (默认: "$HOME/.juicefs/cache" 或 "/var/jfsCache")
--cache-size value 缓存对象的总大小;单位为 MiB (默认: 1024)
--free-space-ratio value 最小残余空间比例 (默认: 0.1)
--cache-partial-only 仅缓存随机小块读 (默认: false)
此外,如果心愿将 JuiceFS 的本地缓存存储在内存中有两种形式,一种是将 --cache-dir
设置为 memory
,另一种是将其设置为 /dev/shm/<cache-dir>
。这两种形式的区别是前者在从新挂载 JuiceFS 文件系统之后缓存数据就清空了,而后者还会保留,性能上两者没有太大差异。
JuiceFS 客户端会尽可能快地把从对象存储下载的数据(包含新上传的小于 1 个 block 大小的数据)写入到缓存目录中,不做压缩和加密。因为 JuiceFS 会为所有写入对象存储的 block 对象生成惟一的名字,而且所有 block 对象不会被批改,因而当文件内容更新时,不必放心缓存的数据生效问题。
当缓存在应用空间达到下限(即缓存大小大于等于 --cache-size
)或磁盘将被存满(即磁盘可用空间比例小于 --free-space-ratio
)时会主动进行清理,目前的规定是依据拜访工夫,优先清理不频繁拜访的文件。
数据缓存能够无效地进步随机读的性能,对于像 Elasticsearch、ClickHouse 等对随机读性能要求更高的利用,倡议将缓存门路设置在速度更快的存储介质上并调配更大的缓存空间。
客户端写缓存
写入数据时,JuiceFS 客户端会把数据缓存在内存,直到当一个 chunk 被写满或通过 close()
或 fsync()
强制操作时,数据才会被上传到对象存储。在调用 fsync()
或 close()
时,客户端会等数据写入对象存储并告诉元数据服务后才会返回,从而确保数据残缺。
在某些状况下,如果本地存储是牢靠的,且本地存储的写入性能显著优于网络写入(如 SSD 盘),能够通过启用异步上传数据的形式进步写入性能,这样一来 close()
操作不会期待数据写入到对象存储,而是在数据写入本地缓存目录就返回。
异步上传性能默认敞开,能够通过以下选项启用:
--writeback 后盾异步上传对象 (默认: false)
当须要短时间写入大量小文件时,倡议应用 --writeback
参数挂载文件系统以进步写入性能,写入实现之后可思考勾销该选项从新挂载以使后续的写入数据取得更高的可靠性。另外,像 MySQL 的增量备份等须要大量随机写操作的场景时也倡议启用 --writeback
。
正告:当启用了异步上传,即挂载文件系统时指定了
--writeback
时,千万不要删除<cache-dir>/<UUID>/rawstaging
目录中的内容,否则会导致数据失落。
当缓存磁盘将被写满时,会暂停写入数据,改为间接上传数据到对象存储(即敞开客户端写缓存性能)。启用异步上传性能时,缓存自身的可靠性与数据写入的可靠性间接相干,对数据可靠性要求高的场景应审慎应用。
总结
最初,分享一个用户们常常会问到的问题「为什么设置了缓存容量为 50 GiB,但理论占用了 60 GiB 的空间?」
对于总量雷同的缓存数据,在不同的文件系统上会有不同的容量计算规定。JuiceFS 目前是通过累加所有被缓存对象的大小并附加固定的开销(4KiB)来估算失去的,这与 du
命令失去的数值并不完全一致。
为避免缓存盘被写满,当缓存目录所在文件系统空间有余时,客户端会尽量减少缓存用量。
通过上述介绍,咱们对 JuiceFS 的缓存机制的原理有了进一步理解。JuiceFS 自身作为底层文件系统,提供了包含元数据缓存、数据读写缓存等多种缓存机制,最大限度的保障了数据的一致性。心愿大家通过本文的理解能更好的利用 JuiceFS。
举荐浏览:知乎 x JuiceFS:利用 JuiceFS 给 Flink 容器启动减速
如有帮忙的话欢送关注咱们我的项目 Juicedata/JuiceFS 哟!(0ᴗ0✿)