有效地从ZFS删除10M +文件


30

我编写了一个有问题的程序,意外地在/ tmp下创建了大约3000万个文件。(该错误是在几周前引入的,它每秒创建两个子目录。)我可以将/ tmp重命名为/ tmp2,现在需要删除文件。系统是FreeBSD 10,根文件系统是zfs。

同时,镜像中的一个驱动器出现故障,我已将其更换。该驱动器有两个120GB SSD磁盘。

这里的问题是:更换硬盘驱动器并重新装入整个阵列需要不到一个小时的时间。删除文件/ tmp2是另一回事。我编写了另一个程序来删除文件,并且它每秒只能删除30-70个子目录。删除所有文件需要2-4天。

重新同步整个阵列需要一个小时,而从磁盘中删除需要4天,这怎么可能?为什么我的表现这么差?每秒70次删除似乎是非常非常差的性能。

我可以手动删除/ tmp2的inode,但这不会释放空间,对吗?

zfs或硬盘驱动器可能有问题吗?


1
我不是zfs专家,所以我无法与您进行性能调优或您可能会做些什么来改进它(这也需要大量信息,并且最好由专家直接完成)。但是,我可以说重新同步发生在块级别,而删除则发生在文件系统级别。删除像这样的十亿兆字节的inode缓冲区时,文件系统将大部分开销。
后台打印程序

请发表您df -hzpool listzfs list
ewwhite

5
写了另一个程序: rm -rf /tmp2不会做这项工作吗?
托尔比约恩Ravn的安徒生

2
您不可以重启吗?/tmp应该是一个tmpfs文件系统,并存储在内存中。
搅拌器

Answers:


31

ZFS中的删除非常昂贵。如果在文件系统上启用了重复数据删除,则更是如此(因为取消引用重复数据删除的文件非常昂贵)。快照也可能使事情复杂化。

您最好删除/tmp目录而不是其中包含的数据。

如果/tmp是ZFS文件系统,请将其删除并重新创建。


1
@nagylzs在这种情况下,我建议将其设置为单独的ZFS文件系统。然后,您可以将当前的/ tmp移开,将新的/ tmp移到适当位置,并在系统空闲时删除文件。结果:ionice在删除运行时,停机时间最少,性能略有下降(假设FreeBSD拥有,则性能可降低)。
CVn

9
我错了。这是一个单独的文件系统。这是起作用的方法:重新引导到单用户模式,然后执行“ zfs删除zroot / tmp; zfs创建zroot / tmp; chmod 41777 / tmp”
nagylzs

6
总停机时间为5分钟。太棒了!:-)
nagylzs

1
好吧,这也说明了我的担忧,即删除快照不会因为快照而释放空间。但是将tmp设置为不进行自动定期快照,吗?
JDługosz

1
实际上,这是:zfs create -o compression = on -o exec = on -o setuid = off zroot / tmp;chmod 1777 / zroot / tmp; zfs set mountpoint = / tmp zroot / tmp; 我不确定如何关闭自动快照。我认为,存在“ zfs set com.sun:auto-snapshot = false”的功能,但仅适用于solaris。
nagylzs

27

重新同步整个阵列需要一个小时,而从磁盘中删除需要4天,这怎么可能?

考虑一栋办公楼。

从所有楼层的所有办公室中移走所有计算机和家具及固定装置需要长时间,但是这些办公室可立即由其他客户使用。

使用RDX拆除整个建筑物快得多,但是下一个客户可能会抱怨这个地方的通风状况。


5
ZFS不是办公楼:)
developerbmw

9
@developerbmw上也实际上没有文件或文件夹,但是我们需要隐喻性的概念来了解正在发生的事情。
JamesRyan 2016年

2
@JamesRyan是的,这实际上是一个很好的类比...我只是个傻子
developerbmw

5

这里发生了很多事情。

首先,所有现代磁盘技术都针对批量传输进行了优化。如果您需要移动100MB的数据,如果它们位于一个连续的块中而不是分散在整个位置,它们的处理速度将更快。SSD在这里有很大帮助,但即使它们更喜欢连续块中的数据。

其次,就磁盘操作而言,重新同步是最佳的选择。您从一个磁盘读取了大量连续的数据块,对其进行了一些快速的CPU操作,然后将其以另一个较大的连续数据块重写到另一个磁盘。如果电源在途中发生故障,没什么大不了的-您将忽略校验和不正确的任何数据,然后按常规进行操作。

第三,删除文件确实很慢。ZFS特别糟糕,但是实际上所有文件系统的删除速度都很慢。他们必须修改磁盘上的大量不同数据块并正确计时(即等待),以便在断电时不会损坏文件系统。

重新同步整个阵列需要一个小时,而从磁盘中删除需要4天,这怎么可能?

重新同步是磁盘真正快的事情,而删除则是磁盘慢的事情。每兆字节的磁盘只需要做一点重新同步即可。您可能在该空间中有一千个文件需要删除。

每秒70次删除似乎是非常非常差的性能

这取决于。我对此不会感到惊讶。您没有提到您正在使用哪种类型的SSD。现代的英特尔和三星固态硬盘在这种操作(读取-修改-写入)方面非常出色,并且性能会更好。较便宜/较旧的SSD(例如Corsair)将很慢。此处每秒的I / O操作数(IOPS)是决定因素。

ZFS 要删除的东西特别慢。通常,它将在后台执行删除操作,因此您不会看到延迟。如果您要执行大量操作,则无法将其隐藏起来,必须延迟您的操作。


附录:为什么删除缓慢?

  • 删除文件需要几个步骤。文件元数据必须标记为“已删除”,最后必须对其进行回收,以便可以重复使用空间。ZFS是一个“日志结构化的文件系统”,如果您仅创建事物而从未删除它们,则其性能最佳。日志结构意味着,如果删除某些内容,则日志中会有一个空白,因此必须重新排列(整理碎片)其他数据以填补空白。这对于用户是不可见的,但是通常很慢。
  • 更改的方式必须是:如果在途中断电,则文件系统将保持一致。通常,这意味着等待磁盘确认数据确实在介质上;对于SSD,可能要花费很长时间(几百毫秒)。这样做的最终结果是,簿记工作更多(即磁盘I / O操作)。
  • 所有的更改都很小。无需读取,写入和擦除整个闪存块(或磁盘的圆柱体),您需要对其进行一些修改。为此,硬件必须读取整个块或柱面,在内存中对其进行修改,然后再次将其写出到介质中。这需要很长时间。

我不了解ZFS,但是某些文件系统允许您取消目录与内容的链接,但是稍后在垃圾回收/碎片整理/清理阶段将这些内容删除。ZFS是否有任何实用程序可以执行此类懒惰删除?它实际上并不会加快OP的删除速度,但是如果它在整理期间隐式发生,可能会减少问题的发生。

2

重新同步整个阵列需要一个小时,而从磁盘中删除需要4天,这怎么可能?

这是可能的,因为这两个操作在文件系统堆栈的不同层上进行。重新同步可以进行低级别操作,实际上不需要查看单个文件,一次可以复制大量数据。

为什么我的表现这么差?每秒70次删除似乎是非常非常差的性能。

它确实需要做很多记账工作。

我可以手动删除/ tmp2的inode,但这不会释放空间,对吗?

我不了解ZFS,但是如果它可以从中自动恢复,那么最终它可能会在后台执行与您已经在做的相同的操作。

zfs或硬盘驱动器可能有问题吗?

zfs scrub什么都没说


2

删除大量文件从来不是真正的快速操作。

为了删除任何文件系统上的文件,您需要读取文件索引,删除(或标记为已删除)索引中的文件条目,删除与该文件关联的所有其他元数据,并将为该文件分配的空间标记为没用过。必须针对要删除的每个文件分别完成此操作,这意味着删除大量文件需要大量小型I / O。以确保在断电情况下数据完整性的方式进行此操作会增加更多开销。

即使没有ZFS引入的特性,删除3000万个文件通常也意味着超过一亿个单独的I / O操作。即使使用快速的SSD,这也将花费很长时间。正如其他人提到的,ZFS的设计进一步加剧了这个问题。


2

伊恩·豪森(Ian Howson)解释了为什么它运行缓慢。

如果并行删除文件,由于删除操作可能会使用相同的块,因此可能会提高速度,从而可以节省多次重写同一块的时间。

因此,请尝试:

find /tmp -print0 | parallel -j100 -0 -n100 rm

并查看其效果是否优于每秒70次删除。


0

如果您反转想法,这非常简单。

  1. 获得第二个驱动器(您似乎已经拥有了)

  2. 使用/ rmp将除/ tmp目录之外的所有内容从驱动器A复制到驱动器B。Rsync将比块复制慢。

  3. 使用驱动器B作为新的引导卷重新引导

  4. 重新格式化驱动器A。

这也会对驱动器进行碎片整理,并为您提供一个全新的目录(很好,碎片整理对于SSD来说并不重要,但是线性化文件不会对任何事情造成损害)


首先复制除/ tmp以外的所有内容吗?那么包括/ dev和/ proc吗?其次,对我来说听起来有些混乱,尤其是在生产服务器上。
亨尼斯

我假设他足够聪明,可以排除非文件,已挂接的卷和虚拟内存文件夹,在这里不能猜到大多数。或从维护启动中进行操作,而这些都不重要。
彼得

我认为您也可以zfs send/recv(块级复制)除根文件系统(在这种情况下位于/ tmp)之外的所有其他文件系统,并手动复制根文件系统上的剩余数据(当然不包括/ tmp)。
user121391'9

2
这将丢失快照并绕过某些可靠性功能。错过了使用zfs的意义。
JDługosz

2
@JDługosz有效积分,但只有在用户关心的情况下才相关。有点像“我的备份已损坏,如何修复?” ->“您需要任何备份文件吗?” ->“不。” ->“重新格式化”。
彼得

-1

在未排序的列表中,您有3000万个条目。您在列表中扫描要删除的条目,然后将其删除。现在,您的未排序列表中只有29,999,999个条目。如果它们都在/ tmp中,为什么不重启?


编辑该信息以反映评论中的信息:问题陈述:删除/ tmp中错误创建的30M +文件中的大多数(但不是全部)要花费很长时间。
问题1)从/ tmp删除大量不需要的文件的最佳方法。
问题2)了解为什么删除文件这么慢。

解决方案1)-/ tmp在大多数* nix发行版的启动时重置为空。但是,FreeBSD并不是其中之一。
第1步-将有趣的文件复制到其他位置。
第2步-以root身份

 $ grep -i tmp /etc/rc.conf  
 clear_tmp_enable="YES" # Clear /tmp at startup.  

步骤3-重新启动。
步骤4-将clear_tmp_enable更改回“否”。
不需要的文件现在消失了,因为FreeBSD上的ZFS 具有以下功能:“销毁数据集比删除驻留在数据集上的所有文件要快得多,因为它不需要扫描所有文件并更新所有相应的元数据。 ” 因此在启动时要做的就是重置/ tmp数据集的元数据。这是非常快的。

解决方案2)为什么这么慢?ZFS是一个很棒的文件系统,其中包括诸如恒定时间目录访问之类的功能。如果您知道自己在做什么,那么效果很好,但是证据表明OP不是ZFS专家。OP并未指出他们是如何尝试删除文件的,但是,我猜测他们会使用“ find regex -exec rm {} \;”的变体。这适用于较小的数字,但无法扩展,因为正在进行三个串行操作:1)获取可用文件列表(以散列顺序返回3000万个文件),2)使用正则表达式选择要删除的下一个文件,3 ),告诉操作系统从3000万个列表中查找并删除该文件。即使如果 ZFS返回从内存和一个列表,如果 “查找”将其缓存,正则表达式仍必须从列表中识别出要处理的下一个文件,然后告诉操作系统更新其元数据以反映该更改,然后更新列表,以便不再对其进行处理。


1
我认为您误解了这个问题。我需要删除大多数文件。也就是说,超过30M个文件。
nagylzs

@nagylzs / tmp在重新启动时被清除。如果要删除大部分,则只保留一部分,即少于一半,因此请复制要保留的部分,然后重新启动以消除其余部分。删除速度如此之慢的原因是,目录中包含大量文件会导致产生大量未排序的列表,需要处理这些列表才能找到要操作的文件,这需要时间。这里唯一的问题是PEBCAK。
保罗·史密斯

Zfs目录未排序?我认为zfs可以很好地处理大型目录。
JDługosz

好吧,/ tmp不会清除,只有X个相关文件。至少在FreeBSD上。在启动时无论如何都无法清除它,因为rc脚本通常需要几天的时间才能删除。
nagylzs

@JDlugosz-ZFS比大多数的要好得多,但是inode列表(所有目录都是未排序的)。
保罗·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.