如何在Linux中提高磁盘IO性能

时间:2020-01-09 10:39:16  来源:igfitidea点击:

在了解如何提高磁盘IO性能之前,我们应该了解Linux环境中的IO流基础。

下面的流程图为我们提供了" IO请求如何在用户空间和设备之间流动的概述"。

  • 用户空间是应用程序运行的地方,底层是设备可用的地方。

  • 现在,用户空间上的应用程序将生成IO请求,这些请求将发送到VFS(虚拟文件系统)的内核接口

  • VFS与诸如etx4,xfs等文件系统有关。

这些是驻留在设备上的基础文件系统。

  • 但是,在IO到达设备之前,它会通过缓冲区高速缓存。

  • 接下来,IO请求将通过IO调度程序。

  • 最后,来自IO调度程序的IO请求将发送到设备。

I/O请求流

  • 首先,在应用程序区域中,我们可以实施一些功能来优化I/O,使其更加高效。

  • 在VFS区域中,我们几乎无法做些调整I/O性能的事情。

  • Next Buffer缓存是IO优化中最重要的部分之一,因为这是为读取和写入请求保留的RAM。
    如果没有足够的缓冲区高速缓存,那么IO速度将受到严重影响

  • 接下来是IO调度程序,它确定操作系统如何与磁盘进行通信。
    IO调度程序有不同类型,每种都有各种可调参数,可以根据需求优化IO性能。

  • 最后是将与设备通信的驱动程序。
    我们还可以通过有时修改驱动程序的各个内核模块甚至BIOS配置来调整IO性能。

了解I/O挑战

为了提高磁盘IO性能,我们必须明确IO面临的IO挑战和问题:

  • HDD具有延迟,因为读/写头需要移动到正确的位置

  • 搜索时间是硬盘将磁头定位在正确轨道上的时间

  • 旋转延迟是HDD等待正确的扇区通过磁头下方的位置

  • 如果数据分散在整个磁盘上,则会浪费大量时间

  • 可以通过重新安排磁盘请求来最大程度地减少磁盘控制器的移动

  • RHEL自动执行此操作,将请求放入队列并运行电梯算法

  • 在电梯算法中,饥饿可能发生在不良算法中:只有中间的楼层才能获得服务

另请阅读:

带有检查和监视磁盘I/O统计信息和性能的15个最佳工具,并带有示例如何在Linux中使用LUKS加密硬盘(分区)

如何使用调度程序提高磁盘IO性能

IO Scheduler的类型

为了提高磁盘IO性能,存在各种I/O调度程序算法(截止日期,完全公平排队(cfq),noop,预期调度程序。
这些已被认为是遗留的,撰写本文时最新的似乎是mq-deadline和预算公平排队(bfq)I/O调度程序,对于重型或者轻型I/O工作负载,bfq看起来非常有前途(bfq是最新添加的内核版本4.16)。

检查当前活动的调度程序

$cat /sys/block/sda/queue/scheduler 
noop deadline [cfq]

此处,bfq是我的Fedora 28系统(具有更新的内核)上使用的I/O调度程序:

$cat /sys/block/sda/queue/scheduler 
mq-deadline [bfq] none

无人电梯

这是最简单的I/O调度算法。
没有有序的队列,新请求总是添加在调度队列的前面或者后面,并且下一个要处理的请求始终是队列中的第一个请求。

CFQ电梯

"完全公平排队"升降机的主要目标是确保在触发I/O请求的所有进程之间公平分配磁盘I/O带宽。
为了获得此结果,电梯利用大量排序的队列(默认情况下为64)来存储来自不同进程的请求。
每当将请求传递到电梯时,内核都会调用一个哈希函数,该函数将当前进程的线程组标识符(通常对应于PID,请参见第3章中的"标识进程"部分)转换为队列;然后,电梯将新请求插入此队列的末尾。
因此,来自同一进程的请求总是插入到同一队列中。

为了重新填充调度队列,电梯实际上以循环方式扫描I/O输入队列,选择第一个非空队列,并将一批请求从该队列移至调度队列的尾部。

最后期限电梯

除调度队列外,"截止"电梯还使用四个队列。
其中两个(已排序的队列)分别包括读取和写入请求,这些请求根据其初始扇区号排序。
其他两个(截止期限队列)包括相同的读写请求,这些请求根据它们的"截止期限"排序。
引入这些队列是为了避免请求匮乏,这种情况发生在电梯策略长时间忽略一个请求时,因为它倾向于处理更接近最后一个服务请求的其他请求。
请求期限本质上是一个过期计时器,当请求传递到电梯时,该计时器开始计时。
默认情况下,读取请求的到期时间为500毫秒,而写入请求的到期时间为5秒-读取请求具有写入请求的特权,因为它们通常会阻止发出请求的进程。
截止日期可确保调度程序一直在等待很长时间,即使它的排序很慢,它也可以查看该请求。

当电梯必须补充调度队列时,它首先确定下一个请求的数据方向。
如果同时发送读写请求,则电梯将选择"读"方向,除非"写"方向已被丢弃过多次(以避免写请求饿死)。

接下来,电梯检查相对于所选方向的期限队列:如果队列中第一个请求的期限已过,则电梯将该请求移至调度队列的末尾;它还会从已排序队列中移出一批请求,从过期的请求开始。
如果请求恰好在磁盘上物理相邻,则此批处理的长度较长,否则较短。

最后,如果没有请求过期,则电梯从从已排序队列中获取的最后一个请求开始,从该请求开始调度一批请求。
当光标到达已排序队列的末尾时,搜索将从顶部("单向电梯")再次开始。

选择哪个升降机来提高磁盘IO性能?

如果硬件有自己的大缓存需要担心," noop"调度程序会将数据快速推向硬件,可以提高性能。

在具有少量I/O容量的台式机系统上,"预期"时间表可以通过更好地将读写请求分为几批来帮助充分利用底层磁盘。
它不太可能适合典型的数据库服务器。

其他两个选项CFQ和Deadline无法建议特定的用例。
原因是确切的行为取决于我们使用的Linux内核以及相关的工作负载。
在某些内核版本中,CFQ的性能很差,并且由于CFQ实现中的错误,截止日期显然更好。
在其他情况下,截止日期将增加延迟,与系统具有高并发水平时人们期望的恰好相反。
而且我们将无法有效地将它们与任何简单的基准进行比较。
CFQ和截止日期之间的主要区别仅在有许多同时发生的读写请求争夺磁盘时间时才会显示出来。
最佳选择完全取决于该组合。

任何告诉我们CFQ或者截止日期始终是提高磁盘IO性能的正确选择的人都不知道他们在说什么。
当我们对应用程序的运行进行合理的模拟时,都值得尝试一下,看看是否由于诸如错误的内核之类的东西而造成了巨大的差异。
尝试测量事务延迟,而不仅仅是平均吞吐量,以最大程度地在此处做出正确选择的几率。