Skip to main content

后台任务

在 JuiceFS 企业版,我们用「后台任务」特指一系列通过元数据服务分发给客户端执行的任务,包括碎片合并、清理回收站过期文件,以及跨区域数据复制。在用词上需要注意区分「后台任务」和「异步任务」,前者在 JuiceFS 有着特定的含义,而「异步任务」则泛指各种异步执行的过程。比方说客户端启用了客户端写缓存后,数据也由客户端异步上传,类似这样的异步执行并不属于「后台任务」,注意区分。

本篇中提及的后台任务类型,无一例外都是在和对象存储打交道,为了对这些任务进行更加精细化的控制(比如对部分客户端禁用后台任务,或者控制碎片合并占用的带宽),你可以通过控制台修改客户端令牌的相关设置,来动态地调整客户端的后台任务设置。

如果没有显式禁用后台任务,那么客户端会无差别地运行该文件系统下所有类型的后台任务(不同文件系统之间的数据仍然严格隔离),这意味着:

  • 如果客户端使用 --subdir 挂载子目录,后台任务的范畴并不会受影响,仍然会运行整个文件系统下所有的后台任务;
  • 使用只读令牌挂载的客户端,将无法运行后台任务。请确保文件系统有读写权限客户端挂载,否则将影响文件系统相关功能的正常运行;
  • 类似地,其他挂载参数也不会影响后台任务运行的范畴,不过这也并不是说挂载参数对后台任务毫无影响:经过参数调优、读写性能更好的客户端,能够更快地完成后台任务,因此元数据服务也会分配更多任务给这些客户端。

碎片合并

所谓「文件碎片」,指的就是 JuiceFS 中 Slice 这个数据结构,在「JuiceFS 如何存储文件」中,我们也详细介绍了文件是如何写入,以及碎片是如何伴随着产生的,继续阅读之前,确保你已经熟悉该原理。

什么是「碎片合并」?简单概括就是:每次文件发生写入,元数据服务都会根据碎片情况判断是否需要合并,然后按照一定的规则派发给客户端执行。客户端执行完毕后,多个 Slice 会被合并为一,提升读效率。如果你发现 JuiceFS 挂载点明明没有文件读写,却存在着不明的读写流量,那么通常都是碎片合并导致的,无需担心。

碎片合并有着以下设计要点:

  • 派发任务的时候,会优先选择发起本次写入的客户端(偏好本地化),令他来执行相关碎片合并任务,考虑到该客户端很可能已经在本地缓存持有需要合并的碎片,这样的设计能够降低读开销;
  • 在同一时间,一个 Chunk 的合并任务,只分配给一个客户端执行,由元数据服务全局调配。

可以通过以下途径对碎片合并的情况进行观测:

  • 从控制台进入文件系统,在监控标签页的「对象存储」板块,碎片合并产生的写入流量以「compact」图线表示;
  • 私有部署 在 Grafana 打开 Meta info 仪表盘,关注 Memory distribution 下的 slices:used 图线,理想情况下,该值应接近 0。需要注意的是,即便注意到 slices:used 用量异常高(百兆到千兆级别),但应用侧的文件系统访问并没有遇到相关性能问题,那么也并不需要做任何特殊处理,继续使用即可(这种情况中,虽然碎片数量总体很高,但真正被访问到的文件保持着良好的碎片化状态,因此总体性能不受影响)。

在不同场景下,碎片合并也可能遭遇一些不同的问题,在下方分别叙述。

碎片合并与写缓存

「客户端写缓存」本身就是一个需要谨慎使用的特性,如果你已经启用了写缓存,那么务必保证客户端有足够的写入性能,让待写入的数据能及时上传。写缓存客户端如果没有足够的写入速度,配合上碎片合并的机制,会让正在合并碎片的文件读取缓慢甚至卡死。这是因为合并后的 Slice 还没来得及上传到对象存储服务,就提交到了元数据。此时其他客户端去读文件,就会卡住不断重试,如果重试期间内,写缓存客户端也没能将待上传的数据写入到对象存储,那么就会超时报错。

碎片合并太慢

碎片积攒过多,会体现为读性能极差(甚至卡死),如果你的问题排查结论是文件碎片化太严重,从以下角度着手处理碎片合并太慢的问题:

  • 后台任务是由客户端负责执行,如果客户端数量太少,又或者是在访问令牌中禁用了后台任务,都会影响碎片合并的运行,确保有足够数量的,并且未关闭后台任务的客户端(任何形式的 JuiceFS 客户端,都计入在内,包括 Hadoop SDK、S3 网关);
  • 不难想象,碎片合并需要先将碎片读取到本地、合并,最后重新写回对象存储并提交给元数据服务,因此如果你所使用的对象存储服务存在性能问题,或者被施加了全局限速,也可能因此导致碎片合并速度太慢;
  • 私有部署 元数据服务也控制着碎片清理的速率,以及总体的客户端空间的任务队列长度,详询 Juicedata 工程师;
  • 特定的文件系统写入模式会带来更多的碎片,比如持续的追加小写(每次追加都调用 flush),JuiceFS 也在持续学习各类场景的写入模式,并进行针对性的优化,如果你的文件系统访问模式带来异常大的碎片量,联系 Juicedata 工程师一起协查、调优。

碎片合并流量过高

特定大文件场景下,碎片合并会产生显著的写入流量,叠加后如果到达了对象存储的限速,会对正常的业务写入造成影响。JuiceFS 为这种情况设计了针对碎片合并的限速功能,可以在「访问控制」页面,对令牌施加碎片合并的限速,在不影响客户端正常写入速度的前提下,限制碎片合并的流量。但也要注意,限速势必会放慢碎片合并的进展,并带来相应的性能风险,因此除了限速外,我们还总结了以下实践:

  • 对于业务容器「转瞬即逝」的场景,使用 Mount Pod 内的客户端进行碎片合并,可能效率不高,考虑用一批稳定常驻的客户端来执行碎片合并,比如「独立缓存集群」节点,避免因客户端生命周期太短,造成碎片合并慢。这样的实践需要为缓存集群和业务侧客户端分配不同的令牌,并对业务侧禁用后台任务,这样一来,只有缓存组的成员才被允许执行后台任务,由他们专门负责碎片合并;
  • 寻求 Juicedata 工程师帮助,分析判断异常数量的碎片的来源,并尝试从源头上减少碎片产生。

清理回收站

JuiceFS 默认启用回收站(创建文件系统时,你会被要求指定回收站的留存时间),因此文件删除以后,会首先进入回收站,等过期时间来临时,才安排删除。这个删除任务也属于后台任务,这也是为什么清空了回收站以后,你可能会注意到对应的对象存储块并没有被释放。即使没有启用回收站,删除文件以后,对象存储上的文件也不会立刻被清理掉——他们会以后台任务的形式,下发到各个客户端进行删除,因此从删除文件到对象存储块被释放,总会存在一段时间间隔。

清理回收站,不难想象就是删除对象存储数据块,然后删除其元数据的过程。既然是和对象存储打交道,同样可能存在太快、太慢的问题,参考下方内容,结合实际情况进行处理:

  • 删除对象太快:删除大量对象时,可能因 DELETE 请求量太大触发限速,甚至消耗过多 CPU。此时可以用 --delete-limit 来限制 QPS。
  • 删除对象太慢:后台任务会分发给所有客户端执行(没有关闭后台任务的客户端),因此如果删除速度太慢,希望更加迅速地释放对象存储空间,可以增加客户端数量。任何形式的 JuiceFS 客户端,都计入在内,包括 Hadoop SDK、S3 网关等。

私有部署用户可以按需自行调整元数据服务设置,因此也可以直接在后台任务层面上来控制删除任务的下发速率,来达到管理删除速度的效果。

回收站和文件碎片

各类随机写、覆盖写产生的文件碎片,虽然在回收站中不可见,但他们一样遵循回收站的时间进行延迟删除。因此,在高频随机写、小追加写场景下,如果启用了回收站,那么会产生大量文件碎片,他们的元数据可能会给元数据服务造成内存压力。

对于私有部署用户,如果高频随机写产生了大量文件碎片,给元数据节点造成内存压力,可以联系 Juicedata 团队,来调整元数据服务配置,为失效文件碎片关闭回收站功能、强制立即删除,来达到释放内存的效果。

数据复制

如果你启用了跨区域数据复制,那么数据复制也会以后台任务的形式执行。如果注意到数据复制的速度不够快、无法打满带宽,同样可以增加客户端数量来加速运行。