优化 ext4 以实现始终完整运行

优化 ext4 以实现始终完整运行

我们的应用程序将数据作为一个巨大的环形缓冲区(30 到 150TB)写入磁盘;写入新文件的同时删除旧文件。因此,根据定义,磁盘始终“接近满”。

作家进程以大约 100-150 Mbits/s 的净输入速度创建各种文件。数据文件是 1GB“数据”文件和几个较小的元数据文件的混合物。 (输入速度是恒定的,但请注意新文件集每两分钟仅创建一次)。

有一个单独的删除器每 30 秒删除“最旧”文件的进程。它会不断删除,直到磁盘上的可用空间达到 15GB。

所以稳定运行时,所有数据分区只有15GB可用空间。

这个问题与文件系统减慢有关,郁闷的丹尼尔评论道:

同步挂起只是意味着文件系统正在努力一致地保存最新的操作。那时它肯定会尝试在磁盘上移动数据。我不知道细节,但我很确定如果你的文件系统碎片严重,ext4 会尝试对此做一些事情。如果文件系统几乎 100% 已满,那就不好了。以接近 100% 的容量利用文件系统的唯一合理方法是使用一些文件静态初始化它,然后就地覆盖这些相同的文件(以避免碎片)。可能最适合 ext2/3。

对于这个应用程序来说,ext4 是一个糟糕的选择吗?既然我们是实时运行的,那么可以对 ext4 进行哪些调整以避免碎片、速度减慢或其他性能限制?从 ext4 进行更改将非常困难......

(重写静态创建的文件意味着重写整个应用程序)

谢谢!

编辑我

服务器连接了 50 到 100 TB 的磁盘(24 个驱动器)。 Areca RAID 控制器将 24 个驱动器作为 RAID-6 raid 集进行管理。

从那里我们分为几个分区/卷,每个卷为 5 到 10TB。所以任何一卷的大小都不会很大。

“写入器”进程找到具有“足够”空间的第一个卷并在那里写入文件。文件写入后,重复该过程。

对于全新机器,卷是按顺序填满的。如果所有卷都“已满”,则“删除程序”进程开始删除最旧的文件,直到有“足够”的空间可用。

随着时间的推移,由于其他进程的作用,文件的时间顺序变得随机分布在所有卷上。

编辑二

运行fsck显示碎片非常低:1 - 2%。然而,与此同时,缓慢的文件系统访问已被追溯到各种系统调用,如fclose()fwrite()ftello(),需要很长时间才能执行(5 到 60 秒!)。

到目前为止还没有解决这个问题。请参阅此问题的更多详细信息:如何调试非常慢(200秒)的fwrite()/ftello()/fclose()?

我已禁用sysstatraid-check查看是否有任何改进。

答案1

原则上,我不明白为什么严格的环形缓冲区写入会对碎片造成任何挑战。看起来似乎很简单。在我看来,这句话是基于更一般的写入工作负载的建议。但是看看链接的问题,我发现你有一个真正的问题......

既然你关心碎片,你应该考虑如何衡量它! e4defrag存在。它只有两个选择。 -c只显示当前状态,不进行碎片整理。 -v显示每个文件的统计信息。所有选项组合均有效(包括无选项)。尽管它没有提供任何明确的方法来限制对正在运行的系统的性能影响,但e4defrag支持在单个文件上运行,因此您可以自己对其进行速率限制。

(XFS也有一个碎片整理工具,虽然我没用过。)

e2freefrag可以显示可用空间碎片。 如果如果您使用 CFQ IO 调度程序,那么您可以使用 降低 IO 优先级来运行它ionice

引用的猜测是错误的,斯蒂芬·基特的回答是正确的。 ext4 不执行任何自动碎片整理。它不会尝试“洗牌”已写入的数据。

放弃这种奇怪的误解就没有理由建议“ext2/ext3”。除此之外,当前内核中不存在 ext3 代码。 ext4代码用于挂载ext3。 ext3 是 ext4 的子集。特别是当您创建相对较大的文件时,不使用范围似乎很愚蠢,而这些是 ext4 特有的功能。

我相信“悬挂”更多时候与日记联系在一起。请参阅(正在进行的文件系统)的评论bcachefs-

尾部延迟多年来一直是 ext4 用户的祸根 - 日志代码和其他地方的依赖性可能导致多线程工作负载上的简单操作(例如取消链接)出现 30 秒以上的延迟。似乎没有人知道如何修复它们。

在 bcachefs 中,线程在 IO 上阻塞的唯一原因是它明确要求(未缓存的读取或 fsync 操作),或资源耗尽 - 完全停止。在进行 IO 时,永远不会持有会阻塞前台操作的锁。虽然 bcachefs 目前还不是一个实时文件系统(它缺乏例如 IO 的实时调度),但很可能有一天它会成为一个实时文件系统。

不要让我解释使用XFS可以在多大程度上避免上述问题。我不知道。但如果您正在考虑测试替代文件系统设置,XFS 是我首先会尝试的。

我正在努力寻找有关在 ext4 上禁用日志记录的影响的大量信息。至少它似乎不是调整性能时考虑的常见选项之一。

我不确定你为什么使用 sys_sync()。通常最好避免(参见例如这里)。我不确定这是否真的解释了你的问题,但在试图缩小范围时遇到的事情似乎很不幸。

答案2

这是另一种方法,但它有些复杂。

创建许多较小的分区,比如说 10 或 20 个。 LVM2在这种情况下可能会派上用场。然后以环形缓冲区的方式使用分区,如下所示:

其中一个分区始终是“活动”分区,新数据将被写入其中,直到完全填满或几乎填满为止。您无需留出任何净空。当活动分区已满或没有足够的可用空间来容纳下一个数据块时,切换到下一个分区,该分区随后将成为活动分区。

您的删除程序进程将始终确保至少有一个完全空的分区可用。如果没有——这是关键部分——它就会简单地重新格式化最旧的分区,创建一个全新的文件系统。这个新分区稍后将能够接收新数据,碎片最少甚至没有碎片。

答案3

该问题几乎肯定是由 ext4 delalloc(延迟分配)默认 ext4 挂载选项引起的。它会导致延迟决定在何处写入新文件,直到同步(显式同步或定期运行的隐式同步):如果文件系统已满,此操作可能涉及在磁盘上移动现有文件以为新文件创建连续空间。

您的问题可以通过在挂载选项中添加 nodelalloc 来解决:这将强制 ext4 在原始写入发生时创建空间(如果需要移动现有文件以腾出空间)。如果文件系统已满,它会减慢原始写入速度,并使其看起来无法使用缓冲区高速缓存进行写入,但这比延迟问题直到必须进行同步更好,因为数据会长时间滞留在文件系统中。如果断电,缓冲区高速缓存可能会丢失。

通常 delalloc 是更可取的,因为它只有在知道要写入的新文件的完整大小后才决定将文件放置在哪里,从而最大限度地减少碎片。然而,即使使用nodelalloc,ext4 也能很好地减少碎片,因为只要有可能,它就会尝试提前选择一个大的空间。

相关内容