限制Linux后台刷新(脏页面)


26

当过多的写入数据挂起(可通过/ proc / sys / vm / dirty_background_ratio进行调整)或达到挂起写入的超时时间(/ proc / sys / vm / dirty_expire_centisecs)时,将在Linux上进行后台刷新。除非达到另一个限制(/ proc / sys / vm / dirty_ratio),否则可能会缓存更多写入的数据。进一步的写操作将被阻止。

从理论上讲,这应该创建一个后台进程,写出脏页而不干扰其他进程。实际上,它会干扰任何进行未缓存读取或同步写入的进程。不好 这是因为后台刷新实际上以100%的设备速度写入,并且此时任何其他设备请求都将被延迟(因为路上的所有队列和写入缓存均已满)。

有没有一种方法可以限制刷新过程每秒执行的请求数量,或者有效地对其他设备I / O进行优先级排序?


也许这是一个发送到linux内核邮件列表的好问题vger.kernel.org/vger-lists.html#linux-kernel

您正在使用什么IO调度程序?
3dinfluence 2010年

尝试了各种方法(cfq,截止日期),但我想只有在不包括电池支持的写缓存的情况下,这些方法才能可靠地工作。就像一个磁盘阵列一样,我以PCIe总线速度(RAM)吞噬了1 GiB数据,然后撞上了现实墙。几秒钟,所有LUN的I / O为零。通过节流冲洗(至少是背景冲洗)来粗略估计实际设备速度将解决该拥塞问题。
korkman 2010年

1
最近,我意识到/ sys / block / sdX / queue / nr_requests是一个主要的可调参数。将其降低到最小(在我的情况下为= 4)可以大大改善并发负载延迟:Sysbench fsync每秒随机写入次数从4(!)跃升至80-90,同时以dd的总线速度进行写入。未加载的性能似乎不受影响。调度程序都是一样的,没有活动或截止期限似乎是最佳的。对于大多数BBWC配置,这可能是正确的。
korkman 2010年

Answers:


20

在使用sysbench进行大量基准测试之后,我得出以下结论:

为了生存(在性能方面)

  • 邪恶的复制过程会淹没脏页
  • 并且存在硬件写缓存(可能也没有)
  • 每秒同步读取或写入(IOPS)至关重要

只需转储所有电梯,队列和脏页缓存。脏页的正确位置在该硬件写缓存的RAM中。

尽可能降低dirty_ratio(或新的dirty_bytes),但要注意顺序吞吐量。在我的特定情况下,最佳值为15 MB(echo 15000000 > dirty_bytes)。

这不是解决方案,而是解决方案,因为GB的RAM现在仅用于读取缓存,而不是脏缓存。为了使脏缓存在这种情况下正常工作,Linux内核后台刷新程序需要平均底层设备接受请求的速度,并相应地调整后台刷新。不容易。


规格和基准进行比较:

dd将磁盘置零时进行了测试,sysbench 取得巨大的成功,将16 kB的10个线程的fsync写操作从33 IOPS提升到700 IOPS(空闲限制:1500 IOPS),将单线程从8 IOPS提升到了400 IOPS。

在没有负载的情况下,IOPS不受影响(〜1500),吞吐量略有降低(从251 MB / s降至216 MB / s)。

dd 呼叫:

dd if=/dev/zero of=dumpfile bs=1024 count=20485672

对于sysbench,准备将test_file.0稀疏化为:

dd if=/dev/zero of=test_file.0 bs=1024 count=10485672

sysbench调用10个线程:

sysbench --test=fileio --file-num=1 --num-threads=10 --file-total-size=10G --file-fsync-all=on --file-test-mode=rndwr --max-time=30 --file-block-size=16384 --max-requests=0 run

sysbench调用一个线程:

sysbench --test=fileio --file-num=1 --num-threads=1 --file-total-size=10G --file-fsync-all=on --file-test-mode=rndwr --max-time=30 --file-block-size=16384 --max-requests=0 run

较小的块显示更大的数字。

--file-block-size = 4096,具有1 GB脏字节:

sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 30 Write, 30 Other = 60 Total
Read 0b  Written 120Kb  Total transferred 120Kb  (3.939Kb/sec)
      0.98 Requests/sec executed

Test execution summary:
      total time:                          30.4642s
      total number of events:              30
      total time taken by event execution: 30.4639
      per-request statistics:
           min:                                 94.36ms
           avg:                               1015.46ms
           max:                               1591.95ms
           approx.  95 percentile:            1591.30ms

Threads fairness:
      events (avg/stddev):           30.0000/0.00
      execution time (avg/stddev):   30.4639/0.00

--file-block-size = 4096,具有15 MB的dirty_bytes:

sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 13524 Write, 13524 Other = 27048 Total
Read 0b  Written 52.828Mb  Total transferred 52.828Mb  (1.7608Mb/sec)
    450.75 Requests/sec executed

Test execution summary:
      total time:                          30.0032s
      total number of events:              13524
      total time taken by event execution: 29.9921
      per-request statistics:
           min:                                  0.10ms
           avg:                                  2.22ms
           max:                                145.75ms
           approx.  95 percentile:              12.35ms

Threads fairness:
      events (avg/stddev):           13524.0000/0.00
      execution time (avg/stddev):   29.9921/0.00

--file-block-size = 4096,在空闲系统上具有15 MB的dirty_bytes:

sysbench 0.4.12:多线程系统评估基准

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 43801 Write, 43801 Other = 87602 Total
Read 0b  Written 171.1Mb  Total transferred 171.1Mb  (5.7032Mb/sec)
 1460.02 Requests/sec executed

Test execution summary:
      total time:                          30.0004s
      total number of events:              43801
      total time taken by event execution: 29.9662
      per-request statistics:
           min:                                  0.10ms
           avg:                                  0.68ms
           max:                                275.50ms
           approx.  95 percentile:               3.28ms

Threads fairness:
      events (avg/stddev):           43801.0000/0.00
      execution time (avg/stddev):   29.9662/0.00

测试系统:

  • Adaptec 5405Z(带保护的512 MB写缓存)
  • 英特尔至强L5520
  • 6 GiB RAM @ 1066 MHz
  • 主板Supermicro X8DTN(5520芯片组)
  • 12个Seagate Barracuda 1 TB磁盘
    • Linux软件RAID 10中的10
  • 内核2.6.32
  • 文件系统XFS
  • Debian不稳定

总而言之,我现在确定此配置在数据库流量的空闲,高负载甚至满负载的情况下都能很好地执行,否则本来会被连续的流量饿死。顺序吞吐量要比两个千兆链路所能传递的要高,因此毫无疑问地降低了吞吐量。


您达到“ 15MB的dirty_buffers最佳”部分的方法是什么?
Marcin '02

1
反复试验。就像,下次改变一半的数量,依此类推,直到我只剩下15 MB并确定IOPS。当前的内核3.2可能表现非常不同,顺便说一句。
korkman '02

2
只是想说谢谢您让我走上了正轨。XenServer节点也有一些类似的问题。原来是PHP-FPM / APC缓存导致脏页。调整APC缓存内存模型为我们解决了这个问题。DiskIO的利用率从20%变为
0。– jeffatrackaid

从逻辑上讲,dirty_bytes如果进程正在平均写入设备的吞吐量,则逻辑上的高度应该足以使CPU在写入进程时不会停顿。如果您的应用程序代码正在执行大量计算的周期,然后再写入大量数据,则将很难进行优化,因为短期平均值与长期平均值有很大差异。正确的解决方案是调整特定于进程的dirty_bytes设置,但据我所知,Linux不支持这种设置。
Mikko Rantalainen

3

即使调整内核参数消除了问题,实际上您的性能问题也可能是由于2012年2月1日固件更新中修复的Adaptec 5405Z控制器上的错误所致。发行说明说:“解决了在高I / O压力下固件可能挂起的问题。” 也许像您所做的那样分散I / O足以阻止触发此错误,但这只是一个猜测。

以下是发行说明:http : //download.adaptec.com/pdfs/readme/relnotes_arc_fw-b18937_asm-18837.pdf

即使您的情况并非如此,但我认为这可以使将来遇到此帖子的用户受益。我们在dmesg输出中看到了类似以下的消息,这些消息最终导致我们进行固件更新:

aacraid: Host adapter abort request (0,0,0,0)
[above was repeated many times]
AAC: Host adapter BLINK LED 0x62
AAC0: adapter kernel panic'd 62.
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000000
Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT,SUGGEST_OK
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000028
Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT,SUGGEST_OK
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000028

以下是具有高I / O挂起修复的固件的发行说明中列出的Adaptec RAID控制器的型号:2045、2405、2405Q,2805、5085、5405、5405Z,5445、5445Z,5805, 5805Q,5805Z,5805ZQ,51245、51645、52445。


1
哇,谢谢你的投入 尽管对我而言并非如此,但您又给了我另一个完全避免使用HW RAID的理由,而转到仅使用HBA的设置。HW RAID仍然具有BBWC的优势,但是随着bcache之类的东西进入内核,甚至消失了。硬件RAID的方面恰恰是您描述的固件错误类型。我确实有另一个具有DRBD设置和高I / O负载的系统,导致固件重置,因此这种情况很少见(可能就是那个错误)。
korkman 2014年

1

包含“ WBT”的内核:

块层的改进,LWN.net

通过写回限制,[块层]尝试使用从CoDel网络调度程序借来的策略来获得最佳性能,而又不增加I / O延迟。CoDel会跟踪观察到的网络数据包的最小延迟,如果超过阈值,它将开始丢弃数据包。I / O子系统不赞成丢弃写操作,但是遵循类似的策略,即内核监视读写操作的最小延迟,如果超过阈值,它将开始降低后台写操作的数量。这已经完成了。此行为已在4.10中添加。阿克斯波说,已经看到了相当不错的结果。

WBT不需要切换到新的blk-mq块层。也就是说,它不适用于CFQ或BFQ I / O调度程序。您可以将WBT与截止日期/ mq-deadline / noop / none调度程序配合使用。我相信它也可以与新的“双绞” I / O调度程序一起使用。

除了缩放队列大小以控制延迟之外,WBT代码还将后台写回请求的数量限制为所计算的队列限制的一部分。

运行时配置位于中/sys/class/block/*/queue/wbt_lat_usec

要寻找的构建配置选项是

/boot/config-4.20.8-200.fc29.x86_64:CONFIG_BLK_WBT=y
/boot/config-4.20.8-200.fc29.x86_64:# CONFIG_BLK_WBT_SQ is not set
/boot/config-4.20.8-200.fc29.x86_64:CONFIG_BLK_WBT_MQ=y

WBT的作者100%确认了您的问题陈述-做得好:-)。

[PATCHSET]块:缓冲的写回限制

从时间的曙光开始,我们的后台缓冲写回就很烂。当我们进行后台缓冲写回时,它对前台活动的影响应该很小。那就是后台活动的定义……但是,只要我记得,沉重缓冲的作家就没有那样的表现。例如,如果我做这样的事情:

$ dd if=/dev/zero of=foo bs=1M count=10k

在我的笔记本电脑上,然后尝试启动chrome,它在缓冲写回完成之前基本上不会启动。或者,对于面向服务器的工作负载,安装大RPM(或类似转速)会对数据库读取或同步写入产生不利影响。发生这种情况时,我会让人大喊大叫。

一些最新测试的结果可以在这里找到:

https://www.facebook.com/axboe/posts/10154074651342933

有关补丁集的详细说明,请参见以前的文章。


我很高兴看到问题已在内核内部得到识别和处理。请记住,blk-mq相当新,也许还不那么成熟
korkman,

@korkman叹了口气,我想我会弄乱报价以避免错误的暗示。我同意这是最近几年添加的内容,可能仍然存在性能下降或更糟的情况。事后,维护人员从fl幸的意义上取消了数据损坏修复程序。 如果使用的内核版本是开发blk-mq的,那么使用“旧版”块层可以避免错误的数量是有争议的。我修复的suspend bug是起源于blk-mq的bug,然后对其进行了重构或某种影响。 github.com/torvalds/linux/commit/1dc3039bc87a
sourcejedi

0

您在/ proc / meminfo中的“肮脏”平均值是多少?通常,该值不应超过/ proc / sys / vm / dirty_ratio。在专用文件服务器上,我将dirty_ratio设置为很高的内存百分比(90),因为我将永远不会超过它。您的dirty_ration过低,当您将其击中时,一切都会碎裂,将其升高。


问题是在达到dirty_ratio时不会阻止进程。我可以。但是,将“脏”数据写到磁盘的“后台”进程却毫不留情地填满了队列,并破坏了IOPS性能。我认为这就是IO饥饿。实际上,将dirty_ratio_bytes设置得非常低(例如1 MB)会很有帮助,因为刷新将几乎立即发生,并且队列将保持为空。缺点是顺序处理的吞吐量可能较低,但这没关系。
korkman

你关掉所有电梯了吗?您还从香草系统中调整了什么?
路加(Luke)2010年

1
查看我的自我解答。故事的结尾是删除脏缓存,并将该部分留给硬件控制器。电梯与HW写缓存无关。控制器拥有自己的电梯算法,因此在软件中安装任何电梯只会增加开销。
korkman 2010年

软件中的Elevevator是一个折衷方案:牺牲延迟以提高带宽。例如,假设在以随机顺序提交的软件队列中有100K个写操作。如果软件升降机可以使用巨大的缓冲区订购这些操作,则最终可能只会向设备发送5K的请求。但是,结果是,延迟可能需要增加100K ops,因为前2K ops和最后1K ops实际上可能在设备上彼此靠近。没有增加的延迟,将不可能合并它们。
Mikko Rantalainen
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.