防止大文件写入冻结系统

斯蒂夫

因此,在Linux桌面上,我正在将一些大文件写入本地磁盘或NFS挂载。

有某种系统缓冲区可缓存要写入的数据。(我认为我的系统在0.5-2GB范围内吗?)

如果缓冲区已满,则所有文件访问块都将有效冻结系统,直到写入完成。(我非常确定,即使读取访问也被阻止。)

我需要配置什么以确保永远不会发生?

我想要的是:

如果某个进程不能足够快地将数据写入磁盘(或网络安装等),则该进程可能会阻塞,直到磁盘出现问题为止,但是其他进程仍可以以合理的速率和延迟读取/写入数据,而不会发生任何中断。

理想情况下,我将能够设置特定类型的程序(cp,git,mplayer,firefox等)可使用的dsik的总读写速率有多少,例如“所有mplayer进程加起来至少10MB / s,无论系统其余部分在做什么但是“无论什么情况,所有mplayer实例加起来至少要达到总速率的50% ”也是可以的。(即,我不太在乎是否可以设置绝对比率或占总比率的比例)。

更重要的是(因为最重要的读/写操作很小),我需要类似的延迟设置。再次,我保证单个进程的读/写操作无论在任何情况下都不会阻塞超过10毫秒(或任何其他时间)的系统其余时间。理想情况下,我会保证“无论系统在做什么,mplayer都不必等待10毫秒以上的时间来进行读/写操作”。

无论有问题的流程如何开始(包括运行该用户的用户等),这都必须起作用,因此“将大型cp封装在ionice中”或任何几乎没有用的东西。如果我记得要使它们停顿,那只会阻止某些任务冻结所有内容,但是cron作业,某个正在运行的守护程序的exec调用又如何呢?

(我想我可以用一个总是使他们离子化的shell脚本来包装最严重的违规者,但是即使如此,通过查看ionice的手册页,似乎仍然可以确切知道它能为我提供什么保证,所以我宁愿选择一个更加系统化的方案和可维护的替代方案。)

致德国牧羊犬

通常,Linux使用缓存将数据异步写入磁盘。但是,可能会发生写请求和实际写之间的时间跨度或未写(脏)数据量非常大的情况。在这种情况下,崩溃将导致大量数据丢失,因此,如果脏缓存变大或变旧,Linux将切换到同步写入。由于还必须遵守写入顺序,因此您不能仅绕过小型IO,而不能保证小型IO完全独立于所有较早的排队写操作。因此,依赖的写入可能会导致巨大的延迟。(这种依赖性也可能在文件系统级别上引起:请参阅https://ext4.wiki.kernel.org/index.php/Ext3_Data%3DOrdered_vs_Data%3DWriteback_mode)。

我的猜测是,您正在经历某种缓冲区膨胀和相关写入的结合。如果您写入一个大文件并具有一个较大的磁盘缓存,那么最终您将不得不写入大量数据,然后才能执行同步写入。在LWN上有一篇很好的文章,描述了问题:https : //lwn.net/Articles/682582/

调度程序的工作仍在进行中,新内核版本的情况可能会变得更好。但是,到目前为止:有一些开关可能会影响Linux上的缓存行为(还有更多开关,请参阅:https : //www.kernel.org/doc/Documentation/sysctl/vm.txt):

  • dirty_ratio:占生成可用磁盘的进程将开始写出脏数据的页面数(占包含可用页面和可回收页面的总可用内存的百分比)。总可用内存不等于系统总内存。
  • dirty_background_ratio:占后台内核刷新程序线程将开始写出脏数据的页面数(占包含可用页面和可回收页面的总可用内存的百分比)。
  • dirty_writeback_centisecs:内核刷新器线程将定期唤醒并将“旧”数据写出到磁盘。此可调参数表示两次唤醒之间的间隔,以百分之一秒为单位。将此设置为零将完全禁用定期回写。
  • dirty_expire_centisecs:此可调参数用于定义何时脏数据足够旧以适合内核刷新程序线程写出。它以百分之一秒为单位表示。下次在刷新程序线程唤醒时,内存脏时间超过此时间间隔的数据将被写出。

在这种情况下,减少最大延迟的最简单解决方案是减少脏磁盘高速缓存的最大数量,并使后台作业尽早写入。当然,在原本较大的缓存将完全阻止同步写入的情况下,这可能会导致性能下降。例如,您可以在/etc/sysctl.conf中配置以下内容:

vm.dirty_background_ratio = 1
vm.dirty_ratio = 5

请注意,适合您系统的值取决于可用RAM的数量和磁盘速度。在极端条件下,上述脏污率可能仍然很大。例如,如果您有100GiB的可用RAM,并且磁盘写入的速度约为100MiB,则上述设置将导致最大数量的5GiB脏缓存,并且可能需要大约50秒的时间来写。使用dirty_bytesdirty_background_bytes也可以以绝对方式设置缓存的值。

您可以尝试的另一件事是切换io调度程序。在当前的内核发行版中,没有noop,最后期限和cfq。如果您使用的是较旧的内核,那么与cfq相比,使用截止时间调度程序可能会遇到更好的响应时间。但是,您必须对其进行测试。在这种情况下,应避免出现Noop现象。还有一个非主线BFQ调度程序,它声称与CFQ相比减少了延迟(http://algo.ing.unimo.it/people/paolo/disk_sched/)。但是,它并不包含在所有发行版中。您可以使用以下方法在运行时检查和切换调度程序:

cat /sys/block/sdX/queue/scheduler 
echo <SCHEDULER_NAME> > /sys/block/sdX/queue/scheduler

第一个命令还将为您提供可用调度程序及其确切名称的摘要。请注意:重新启动后,该设置将丢失。要永久选择时间表,您可以添加一个内核参数:

elevator=<SCHEDULER_NAME>

NFS的情况与此类似,但还存在其他问题。以下两个错误报告可能会提供一些有关NFS的处理状态的内幕,以及为什么写入大文件会导致状态非常慢的原因:

https://bugzilla.redhat.com/show_bug.cgi?id=688232 https://bugzilla.redhat.com/show_bug.cgi?id=469848

更新:(2017年8月14日)内核4.10新内核选项CONFIG_BLK_WBT及其子选项BLK_WBT_SQ,并CONFIG_BLK_WBT_MQ相继出台。它们可以防止由硬件缓冲区引起的缓冲区膨胀,该缓冲区缓冲区的大小和优先级不能由内核控制:

Enabling this option enables the block layer to throttle buffered
background writeback from the VM, making it more smooth and having
less impact on foreground operations. The throttling is done
dynamically on an algorithm loosely based on CoDel, factoring in
the realtime performance of the disk

此外,BFQ-Scheduler的内核为4.12。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

写入大文件并挂起

来自分类Dev

如何防止dd冻结系统?

来自分类Dev

使用QTcpSocket发送大文件时冻结

来自分类Dev

下载大文件挂起系统

来自分类Dev

放大文件系统映像

来自分类Dev

Flash死后,如何防止systemd冻结系统?

来自分类Dev

如何加快大文件的写入过程?

来自分类Dev

Python在大文件写入时静默挂起

来自分类Dev

快速进行大文件系统备份

来自分类Dev

如何防止进程写入系统日志?

来自分类Dev

将大文件移至外部磁盘时屏幕冻结

来自分类Dev

将大文件移至外部磁盘时屏幕冻结

来自分类Dev

写入文件Java时程序冻结

来自分类Dev

如何防止进程写入文件

来自分类Dev

对 android 文件系统的写入权限

来自分类Dev

具有大文件支持的跨平台可用文件系统

来自分类Dev

在根文件系统中查找所有大文件

来自分类Dev

从大文件读取数据/向大文件写入数据哪种方法更好?

来自分类Dev

将文件写入Tizen文件系统

来自分类Dev

将.zip存档中的大文件写入Pandas数据框

来自分类Dev

用delphi写入大文件的正确方法是什么

来自分类Dev

将大文件写入磁盘内存不足异常

来自分类Dev

ZFS如何在写入时复制大文件

来自分类Dev

使用Java NIO读取和写入大文件

来自分类Dev

如何防止从服务器端上传大文件

来自分类Dev

合并大文件。如何防止熊猫合并中的重复项?

来自分类Dev

翻译大文件时如何防止会话用完

来自分类Dev

在Mac OS X系统上快速创建大文件?

来自分类Dev

爬网大文件系统的最佳策略是什么?