Linux 上的 SSD IOPS,DIRECT 比缓冲、fio 快得多

seg*_*sai 4 linux raid performance ssd

我有一个 30Tb 大小的硬件 RAID-6 系统 (LSI 9280-8e),由 10 个 DC-S4500 Intel SSD 组成,用于数据库用途。具有 3.2 内核的操作系统 Debian 7.11。文件系统是使用 nobarrier 选项安装的 XFS。

看到与我在随机 I/O 中的预期性能相比有些缓慢,我开始通过运行 fio 基准测试来调查发生了什么。令我惊讶的是,当我在随机读取设置(iodepth=32 和 ioengine=libaio)中对 1Tb 文件使用 fio 时,我得到了 ~ 3000 IOPS,这远低于我的预期。

random-read: (groupid=0, jobs=1): err= 0: pid=128531
  read : io=233364KB, bw=19149KB/s, iops=4787 , runt= 12187msec
  ...
  cpu          : usr=1.94%, sys=5.81%, ctx=58484, majf=0, minf=53
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=99.9%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued    : total=r=58341/w=0/d=0, short=r=0/w=0/d=0
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用 direct=1 选项(即绕过 linux 的缓冲区缓存),我会得到 ~ 40000 IOPS,这是我希望看到的。

random-read: (groupid=0, jobs=1): err= 0: pid=130252
  read : io=2063.7MB, bw=182028KB/s, iops=45507 , runt= 11609msec
....
  cpu          : usr=6.93%, sys=23.29%, ctx=56503, majf=0, minf=54
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=100.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued    : total=r=528291/w=0/d=0, short=r=0/w=0/d=0
Run Code Online (Sandbox Code Playgroud)

我似乎以调度程序、预读和旋转设置的形式为 SSD 分区设置了所有正确的设置。

root@XX:~# cat /sys/block/sdd/queue/scheduler
[noop] deadline cfq 
root@XX:~# cat /sys/block/sdd/queue/rotational
0
root@XX:~# blockdev --getra /dev/sdd
0
Run Code Online (Sandbox Code Playgroud)

我是否仍然错过了降低缓冲性能的东西?或者预计会看到 DIRECT 与 buffered 之间的这种差异?

我还查看了两次运行期间的 iostat 输出这是使用 direct=1 时的情况:

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sdd               0.00     0.00 48110.00    0.00 192544.00     0.00     8.00    27.83    0.58    0.58    0.00   0.02  99.60
Run Code Online (Sandbox Code Playgroud)

这是一个缓冲运行

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sdd               0.00     0.00 4863.00    0.00 19780.00     0.00     8.13     0.89    0.18    0.18    0.00   0.18  85.60
Run Code Online (Sandbox Code Playgroud)

所以看起来关键的区别是队列大小 (avgqu-sz),当使用缓冲 I/O 时它很小。鉴于 nr_requests 和 queue_depth 都很高,我觉得很奇怪:

root@XX:~# cat /sys/block/sdd/queue/nr_requests
128
root@XX:~# cat /sys/block/sda/device/queue_depth
256
Run Code Online (Sandbox Code Playgroud)

这里有什么建议吗?

Joh*_*ald 8

带有 3.2 内核的 D​​ebian 7.11

尽可能升级。您不仅获得了内核改进,而且 Wheezy 已结束生命。


是的,当 direct=1 时,您会看到更高的利用率和队列深度。fio 手册特别提到了这种情况(强调我的):

iodepth=int

要针对文件保持运行的 I/O 单元数。请注意,将 iodepth 增加到 1 以上不会影响同步 ioengines(使用 verify_async 时的小度数除外)。即使是异步引擎也可能施加操作系统限制,导致无法实现所需的深度。在 Linux 上使用 libaio 且未设置 direct=1 时可能会发生这种情况,因为缓冲 I/O 在该操作系统上不是异步的。密切关注 fio 输出中的 I/O 深度分布,以验证实现的深度是否符合预期

所以 libaio 需要 O_DIRECT 来实现异步,这是一个需要了解的重要实现细节。有人问如果不直接用 libaio 是个好主意:

使用libaio时设置direct=0是否有效?

你可以这样做,但我不会推荐它。对于今天的 Linux 内核,如果没有 O_DIRECT 可以限制实现的并行 I/O 数量,libaio 提交可能会变成阻塞(因此不再是异步的)。有一个强有力的论点认为 fio 示例不应该鼓励这样的选项组合......

man doc中的“排队”行为是什么意思?

如果您的意思是“请注意,Linux 可能仅支持具有非缓冲 I/O 的排队行为”这句话(在 http://fio.readthedocs.io/en/latest/fio_doc.html#io-engine 中),我认为它是试图说:

“而不是阻塞提交系统调用直到 I/O 下降并从最低的磁盘设备返回(阻塞行为),当使用 direct=1 和 libaio 时,您可以提交 I/O 并让它异步排队内核允许提交系统调用立即返回,并为您提供在 I/O 完成之前将其他提交排队的机会”。

还可以尝试使用 ioengine=psync 和 direct=0 进行控制测试。即使是带有缓存的同步写入也可以执行大量 IOPS。

所有这些都回避了真正的问题:您正在运行的数据库工作负载有什么问题?问题症状、软件版本、配置、性能指标 (iostat)。DBMS 的 I/O 实现可能与您模拟的、使用的系统调用、执行 I/O 的多个文件和作业、任何数量的事情都大不相同。如果您想进一步调查,这值得自己提出问题。