我编写了一个错误的程序,它意外地在 /tmp 下创建了大约 30M 的文件。(这个错误是几周前引入的,它每秒创建几个子目录。)我可以将 /tmp 重命名为 /tmp2,现在我需要删除这些文件。系统是 FreeBSD 10,根文件系统是 zfs。
与此同时,镜像中的一个驱动器出了问题,我已经更换了它。该驱动器有两个 120GB SSD 磁盘。
问题是:更换硬盘驱动器并重新同步整个阵列只用了不到一个小时。删除文件 /tmp2 是另一回事。我编写了另一个程序来删除文件,它每秒只能删除 30-70 个子目录。删除所有文件需要 2-4 天。
重新同步整个阵列需要一个小时,但从磁盘中删除需要 4 天,这怎么可能?为什么我的表现这么差?70 次删除/秒似乎非常非常糟糕的性能。
我可以手动删除 /tmp2 的 inode,但这不会释放空间,对吧?
这可能是 zfs 或硬盘驱动器的问题吗?
ZFS 中的删除代价高昂。如果您在文件系统上启用了重复数据删除,则更是如此(因为取消引用重复数据文件的成本很高)。快照也可能使事情复杂化。
您最好删除
/tmp
目录而不是其中包含的数据。如果
/tmp
是 ZFS 文件系统,请将其删除并重新创建。考虑一栋办公楼。
从所有楼层的所有办公室移除所有计算机、家具和固定装置需要很长时间,但办公室可以立即供其他客户使用。
使用 RDX 拆除整栋建筑要快得多,但下一个客户很可能会抱怨这个地方有多通风。
这里发生了很多事情。
首先,所有现代磁盘技术都针对批量传输进行了优化。如果您需要移动 100MB 的数据,如果它们位于一个连续的块中而不是分散在各处,它们会做得更快。SSD 在这里有很大帮助,但即使他们更喜欢连续块中的数据。
其次,就磁盘操作而言,重新同步是非常理想的。您从一个磁盘读取大量连续的数据,对其执行一些快速的 CPU 操作,然后将其以另一个连续的大块重写到另一个磁盘。如果电源在中途出现故障,没什么大不了的 - 您只需忽略校验和错误的任何数据并照常进行。
第三,删除文件真的很慢。ZFS 特别糟糕,但实际上所有文件系统的删除速度都很慢。他们必须修改磁盘上大量不同的数据块并正确计时(即等待),以便在电源故障时不会损坏文件系统。
重新同步是磁盘速度非常快的事情,而删除是磁盘速度很慢的事情。每兆字节的磁盘,你只需要做一点点重新同步。您可能在该空间中有上千个文件需要删除。
这取决于。我不会对此感到惊讶。您还没有提到您使用的是哪种类型的 SSD。现代英特尔和三星 SSD 非常擅长这种操作(读取-修改-写入),并且性能会更好。更便宜/更旧的 SSD(例如 Corsair)会很慢。每秒 I/O 操作数 (IOPS) 是这里的决定因素。
ZFS删除东西特别慢。通常,它将在后台执行删除,因此您看不到延迟。如果你正在做大量的事情,它就无法隐藏它并且必须延迟你。
附录:为什么删除很慢?
Ian Howson 给出了一个很好的答案,解释了为什么它很慢。
如果您并行删除文件,您可能会看到速度增加,因为删除可能使用相同的块,因此可以节省多次重写相同的块。
所以试试:
看看它是否比每秒 70 次删除更好。
这是可能的,因为这两个操作在文件系统堆栈的不同层上工作。重新同步可以在低级别运行,实际上不需要查看单个文件,一次复制大量数据。
它确实需要做很多簿记...
我不知道 ZFS,但如果它可以自动从中恢复,它最终可能会在后台执行您已经在执行的相同操作。
zfs scrub
有话说吗?删除大量文件从来都不是真正的快速操作。
为了删除任何文件系统上的文件,您需要读取文件索引,删除(或标记为已删除)索引中的文件条目,删除与文件关联的任何其他元数据,并将为文件分配的空间标记为没用过。这必须针对要删除的每个文件单独完成,这意味着删除大量文件需要大量小型 I/O。在发生电源故障时以确保数据完整性的方式执行此操作会增加更多开销。
即使没有 ZFS 引入的特性,删除 3000 万个文件通常也意味着超过一亿个单独的 I/O 操作。即使使用快速 SSD,这也需要很长时间。正如其他人所提到的,ZFS 的设计进一步加剧了这个问题。
如果你颠倒你的想法很简单。
获得第二个驱动器(您似乎已经拥有了)
使用 rsync 将所有内容从驱动器 A 复制到驱动器 B,不包括 /tmp 目录。Rsync 会比块复制慢。
重新启动,使用驱动器 B 作为新的启动卷
重新格式化驱动器 A。
这还将对您的驱动器进行碎片整理并为您提供一个新目录(很好,碎片整理对于 SSD 而言并不那么重要,但线性化您的文件不会伤害任何东西)
您在未排序的列表中有 3000 万个条目。您扫描列表以查找要删除的条目,然后将其删除。现在您的未排序列表中只有 29,999,999 个条目。如果它们都在 /tmp 中,为什么不直接重新启动?
编辑以反映评论中的信息:问题陈述:删除 /tmp 中 30M+ 错误创建的文件中的大部分(但不是全部)需要很长时间。
问题 1) 从 /tmp 中删除大量不需要的文件的最佳方法。
问题2)了解为什么删除文件这么慢。
解决方案 1) - 大多数 *nix 发行版在启动时将 /tmp 重置为空。然而,FreeBSD 不是其中之一。
第 1 步 - 将有趣的文件复制到其他地方。
第 2 步 - 作为根
第 3 步 - 重新启动。
第 4 步 - 将 clear_tmp_enable 改回“否”。
现在不需要的文件已经消失,因为FreeBSD上的 ZFS 具有“销毁数据集比删除驻留在数据集上的所有文件要快得多,因为它不涉及扫描所有文件并更新所有相应的元数据。 " 所以它在启动时所要做的就是重置 /tmp 数据集的元数据。这非常快。
解决方案2)为什么这么慢?ZFS 是一个很棒的文件系统,它包括诸如恒定时间目录访问等功能。如果您知道自己在做什么,这很有效,但有证据表明 OP 不是 ZFS 专家。OP 没有说明他们是如何尝试删除文件的,但我猜测,我会说他们使用了“find regex -exec rm {} \;”的变体。这适用于小数字,但无法扩展,因为正在进行三个串行操作 1)获取可用文件列表(按哈希顺序返回 3000 万个文件),2)使用正则表达式选择下一个要删除的文件,3 ) 告诉操作系统从 3000 万个列表中查找并删除该文件。即使ZFS 从内存中返回一个列表并且如果'find' 缓存它,正则表达式仍然必须从列表中识别下一个要处理的文件,然后告诉操作系统更新其元数据以反映该更改,然后更新列表,使其不再被处理。