探秘I/O队列对磁盘性能的影响

转载请在文首保留原文出处:EMC中文支持论坛https://community.emc.com/go/chinese
介绍

信息传输过程中数据通常暂存于磁盘队列。实验表明,随着服务器性能的不断提高,磁盘I/O队列常常成为影响磁盘响应速度的首要瓶颈。本文以AIX系统为例,描述了I/O队列在磁盘中的工作原理、监测命令,以及如何对其进行优化以提升磁盘性能。

使用I/O队列的意义:

为何要对磁盘I/O进行并行处理呢?主要目的是提升应用程序的性能。这一点对于多物理磁盘组成的虚拟磁盘(或LUN)显得尤为重要。如果一次提交一个I/O,虽然响应时间较短,但系统的吞吐量很小。相比较而言,一次提交多个I/O既缩短了磁头移动距离(通过电梯算法),同时也能够提升IOPS。假如一部电梯一次只能搭乘一人,那么每个人一但乘上电梯,就能快速达到目的地(响应时间),但需要耗费较长的等待时间(队列长度)。因此一次向磁盘系统提交多个I/O能够平衡吞吐量和整体响应时间。

理论上,磁盘的IOPS取决于队列长度÷平均IO响应时间。假设队列长度为3,平均IO响应时间是10ms,则最大吞吐量是300 IOPS。

IO队列位于何处:
以AIX系统为例,从应用层到磁盘物理层的IO堆栈如下所示,IO按照从上至下的顺序遍历堆栈:
应用程序层
文件系统层(可选)
LVM设备驱动层(可选)
SDD或SDDPCM或其他多路径驱动层(如果使用)
hdisk设备驱动层
adapter设备驱动层
磁盘接口层
磁盘子系统层
磁盘层

AIX在每一层堆栈都会监测IO,因此堆栈的每一层都有IO队列。通常,如果当前各层执行的IO超过了队列长度所限制的最大数量,这些IO将暂存于等待队列中,直至获取申请资源。在文件系统层,文件系统缓存限制了各文件系统的最大可执行IO数量。LVM设备驱动层,可执行的最大IO数量受hdisk缓存的限制。在SDD层,如果dpo设备的qdepth_enable属性设置成yes,则会建立IO队列,但也有些版本无法设置队列。SDDPCM在将IO发送至磁盘设备驱动层之前没有进行队列处理。hdisk通过queue_depth参数设置最大响应IO数量, 而FC适配层的参数为num_cmd_elems。磁盘子系统层有IO队列,单块物理磁盘可接收多个IO请求但一次只能处理一个IO。

IO队列监测命令:

以AIX为例,AIX 5.3及以上版本,可用iostat和sar –d命令监测hdisk队列,iostat -D命令输出如下:
hdisk6 xfer: %tm_act bps tps bread bwrtn
4.7 2.2M 19.0 0.0 2.2M
read: rps avgserv minserv maxserv timeouts fails
0.0 0.0 0.0 0.0 0 0
write: wps avgserv minserv maxserv timeouts fails
19.0 38.9 1.1 190.2 0 0
queue: avgtime mintime maxtime avgwqsz avgsqsz sqfull
15.0 0.0 83.7 0.0 0.0 136

这里,avgwqsz是平均等待队列长度,avgsqsz是平均响应队列长度。在等待队列中花费的平均等待时间是avgtime。sqfull值代表每秒钟向已满队列提交的IO数。对于有cache的磁盘子系统,IO响应时间会有所不同。iostat –D命令显示的是系统从启动后的统计数据。

从应用程序的角度来看,处理IO的总时间是响应时间加上在hdisk等待队列中的时间。
sar –d命令输出如下:
16:50:59 device %busy avque r+w/s Kbs/s avwait avserv
16:51:00 hdisk1 0 0.0 0 0 0.0 0.0
hdisk0 0 0.0 0 0 0.0 0.0
avwait和avserv分别是花费在等待队列和响应队列的时间,avque在AIX 5.3以上版本中,代表等待队列中的平均IO数量。

优化方法:

首先,不应盲目增加以上队列参数值。这样有可能造成磁盘子系统过载或在启动时引起设备配置报错。因此,仅增加hdisk的queue_depths值并不是最好的方法,而应该同时调整可提交最大IO数量。当queue_depths和发送至磁盘子系统的IO数量同时增加时,IO响应时间可能会增加,但同时吞吐量也得到了提升。当IO响应时间接近磁盘超时时间,则说明所提交IO超过了磁盘能够处理的界限。如果看到IO超时并在错误日志中报出IO无法完成,说明可能有硬件问题,或需要缩短队列。

调整queue_depths的一条法则是:对于随机读写或队列未满的情况,如果IO响应时间超过15ms,就不能再增加queue_depths值。一旦IO响应时间增加,瓶颈就从磁盘和adapter队列转移至磁盘子系统。调整队列长度应依据:1)实际应用程序产生的IO请求数,2)使用测试工具以观察磁盘子系统的处理能力。其中,1)为主要依据。

IO队列有以下四种状态:
队列已满,IO等在hdisk或adapter驱动层
队列未满,IO响应时间短
队列未满,IO响应时间长
队列未满,IO提交速度快于存储处理速度并导致IO丢失

我们需要把队列调整为2或3的状态。情况3表明瓶颈不在hdisk驱动层,而很有可能在磁盘子系统自身,也有可能位于adapter驱动层或SAN。

第4种情况是应该避免的。受限于存储IO请求和数据的内存大小,所有磁盘和磁盘子系统都有IO执行数量的限制。当存储丢失IO时,主机端超时,IO将被重新提交,同时等待该IO的事件将被暂停。CPU为了处理IO多做了很多事情,这种情况应该避免。如果IO最终失败,将会导致应用程序崩溃或更严重的结果。所以必须仔细确认存储的处理极限。

合理的平均IO响应时间:

假设队列中没有IO,一次读操作将会占据0至15ms,取决于寻址时间,磁盘转速,以及数据传输时间。之后数据从存储移动至主机。有时数据位于磁盘读缓存,这种情况下IO响应时间约为1ms。对于大型磁盘系统在正常工作状态下,平均IO响应时间约为5-10ms。当随机读取小数据耗时超过15ms时,表明存储较为繁忙。

写操作通常将数据写入cache中,平均耗时不到2.5ms。但是也有例外:如果存储同步将数据镜像至远端,写操作将耗费更长时间。如果写入数据量较大(多于64KB)则数据传输时间会显著增加。没有cache的情况下,写时间的读时间差不多。

如果IO是大块顺序读写,除了传输时间较长,IO会暂存于磁盘物理层队列,IO响应时间远高于平均值。例如:应用提交50个IO(50个64KB顺序读),最初几个IO会获得较快的响应时间,而最后一个IO必须等待其他49个完成,从而耗费很长的响应时间。

评论关闭。