使用iostata观察块设备性能

iostat工具常用来观察块设备的一些指标。
已经有很多文章讨论过,iostat的各项指标代表着什么,又是如何计算出来的,有哪些常见的理解误区。
因此,这里仅仅从存储行业POC的角度来谈谈如何理解iostat的指标,如何分析存储性能。

1. %iowait值很高,说明存储系统有性能瓶颈?

%iowait,代表着cpu等待I/O完成的时间百分比。
看一下iowait产生的条件,一是,系统在等待I/O; 二是,这期间没有其他进程使用cpu(cpu空闲)。
在一般的存储测试项目中,服务器上往往只有测试工具在运行。乍一看,好像的确能够说明,如果iowait值很高,代表着很多I/O未完成,也就说明存储系统有性能瓶颈。

但我们要时刻记住,iowait是用来描述cpu状态的,而不是磁盘。就算描述cpu状态,实际上也不准确。我们这里不对iowait描述cpu状态是否准确做讨论。有兴趣的朋友可以看一下这篇文章The precise meaning of I/O wait time in Linux

1.1. aio不会产生iowait

首先,异步I/O不会产生iowait,不论磁盘有多繁忙。很好理解,由于aio是异步的,CPU不需要IDLE等待IO,也就不会产生%iowait。
使用Fio生成libaio、sync两种I/O请求,脚本如下:

1
2
3
4
5
6
7
8
[WriteFiles]
ioengine=libaio
;ioengine=sync
direct=1
bs=4k
rw=write
iodepth=128
filename=/dev/sdb

iostat -xdmc sdb 1的输出如下(截取某一秒数据)

1
2
3
4
5
6
7
8
9
10
11
12
# sync
avg-cpu: %user %nice %system %iowait %steal %idle
0.4% 0.0% 3.3% 9.7% 0.0% 86.7%

r/s w/s rMB/s wMB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util Device
0.00 4867.00 0.0k 19.0M 0.00 0.00 0.0% 0.0% 0.00 0.18 0.04 0.0k 4.0k 0.20 97.1% sdb
# libaio
avg-cpu: %user %nice %system %iowait %steal %idle
1.0% 0.0% 3.4% 0.0% 0.0% 95.6%

r/s w/s rMB/s wMB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util Device
0.00 18501.00 0.0k 72.3M 0.00 0.00 0.0% 0.0% 0.00 6.76 115.82 0.0k 4.0k 0.05 97.0% sdb

从上面的结果可以看到,两种方式磁盘繁忙度%util指标(也不可信)都达到了97%左右。使用sync时,iowait值为9.7%;使用libaio时w_await到了115ms左右了,但是cpu的iowait还是为0。
这就直接明了的结束了话题! iowait不是用来描述磁盘性能的。

但不免许多客户(keke)不甘心,”不是用来描述磁盘的指标,但也可以间接反映出磁盘的性能” 。我们还是更加详细说明一下。

1.2. cpu繁忙度影响%iowait值

在I/O完全一样的情况下,CPU闲忙状态的变化能够影响%iowait的值。在CPU繁忙期间发生的I/O,无论IO是多还是少,%iowait都不会变;当CPU繁忙程度下降时,有一部分IO落入CPU空闲时间段内,导致%iowait升高。

我们还是用Fio来验证一下,下面的参数文件同时执行两个任务。一个是常规的写盘,一个是纯占用cpu。为了方便观察我们固定使用一个CPU核心,同时设置IOPS为2000。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[writeDisk]
ioengine=sync
direct=1
bs=4k
rate_iops=,2000
rw=write
cpus_allowed=2
filename=/dev/sdb

[cpu_load]
ioengine=cpuio
cpuload=1
;cpuload=70
cpus_allowed=2

首先,将cpu_load任务的cpu占用设置为1,可以理解为几乎是写盘操作,来看下CPU的%iowait指标,由于iostat的输出中是全部的CPU指标,因此这里用top来观察具体的一个CPU。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
top - 17:21:54 up 1 day, 23 min,  3 users,  load average: 0.61, 1.20, 4.82
Tasks: 235 total, 1 running, 234 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 4.6 us, 5.9 sy, 0.0 ni, 35.5 id, 50.0 wa, 0.0 hi, 3.9 si, 0.0 st
...
...
%Cpu7 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
# iostat统计
avg-cpu: %user %nice %system %iowait %steal %idle
0.38 0.00 0.50 3.38 0.00 95.74

Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
dm-1 0.00 0.00 0.00 2000.00 0.00 7.81 8.00 0.49 0.24 0.00 0.24 0.24 48.60

可以看到,CPU2的%iowait为50%左右,整体%iowait的值为3.4%左右。
接着,我们将cpu_load任务的cpu占比设置为70,来看一下结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
top - 17:23:20 up 1 day, 25 min,  3 users,  load average: 0.91, 1.13, 4.48
Tasks: 234 total, 2 running, 232 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni, 99.7 id, 0.3 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 68.7 us, 2.0 sy, 0.0 ni, 11.7 id, 16.3 wa, 0.0 hi, 1.3 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
...
...
%Cpu7 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
# iostat统计
avg-cpu: %user %nice %system %iowait %steal %idle
4.08 0.00 0.50 1.07 0.00 94.35

Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
dm-1 0.00 0.00 0.00 2000.00 0.00 7.81 8.00 0.89 0.45 0.00 0.45 0.45 89.00

可以看到,此时CPU2的%iowait为16%左右,整体%iowait为1%左右。而此时磁盘性能没有什么改变。
我们可以得到开始的结论,CPU的闲忙程度影响%iowait的值。在真实的场景下,成百上千的程序在运行,单靠%iowait值升高判定存储系统存在性能瓶颈是不恰当的。

1.3. I/O并发度影响%iowait值

假设CPU的繁忙状况保持不变的条件下,即使 %iowait 升高也不能说明I/O负载加重了。
如果2个I/O请求依次提交、使得整个时段内始终有I/O在进行,那么 %iowait 是100%;
如果3个I/O请求同时提交,因为系统有能力同时处理多个I/O,所以3个并发的I/O从开始到结束的时间与一个I/O一样,%iowait 的结果只有50%。
2个I/O使 %iowait 达到了100%,3个I/O的 %iowait 却只有50%,显然 %iowait 的高低与I/O的多少没有必然关系,而是与I/O的并发度相关。所以,仅凭 %iowait 的上升不能得出I/O负载增加 的结论。

1
2
3
4
5
6
7
8
[writeDisk]
ioengine=psync
direct=1
bs=4k
rw=write
cpus_allowed=2
;numjobs=8
filename=/dev/sdb

不设置并发时,

1
%Cpu2  :  4.5 us, 13.1 sy,  0.0 ni,  0.0 id, 78.4 wa,  0.7 hi,  3.4 si,  0.0 st

设置numjobs=8时,

1
%Cpu2  : 11.4 us, 41.5 sy,  0.0 ni,  0.0 id, 37.7 wa,  2.1 hi,  7.3 si,  0.0 st

上面都是从反面进行验证说明,那么能不能够直接论证%iowait升高和磁盘I/O性能无关呢?很抱歉,答案是不能。我们只能说明%iowait升高不能够直接反映磁盘出现瓶颈。
当I/O超过磁盘负载能力,必定会导致I/O等待,也就有可能会造成%iowait值升高。但要得到这个结论,条件是非常严苛的。

最后,再次说明%iowait是用来描述cpu状态的,而不是磁盘的指标,也不能间接反映存储系统性能

2. %util

%util并不能准确反映存储设备使用率(或者称为繁忙度)。
%util达到100%,只表示队列中一直有I/O请求,不能说明磁盘的性能达到了瓶颈。因为按照%util的计算规则,只能反映传统的HHD盘串行处理IO的能力。在做RAID和SSD中,可以并行地处理IO,情况就不太适用。
在sysstat最新文档中也已经注明:

1
2
3
4
%util
Percentage of elapsed time during which I/O requests were issued to the device (bandwidth utilization for the device).
Device saturation occurs when this value is close to 100% for devices serving requests serially.
But for devices serving requests in parallel, such as RAID arrays and modern SSDs, this number does not reflect their performance limits.

验证很简单,提升并发数观察一下磁盘性能和%util的值就行了。

3. await

await = ((所有读IO的时间)+(所有写IO的时间))/((读请求的个数) + (写请求的个数))
await = IO 平均处理时间 + IO在队列的平均等待时间
await统计的IO时间包括IO在队列的时间,因此不能武断的认为await值比较高,就说明这块盘的处理能力不行。保持磁盘压力不变的情况下,增加队列深度即可验证这个问题。
#1.2. cpu繁忙度影响%iowait值 中,我们也可以看到,cpu的闲忙程度影响了I/O队列的效率(avgqu-sz),也就影响了await的值。但此时存储设备的性能没有变化。

如果怀疑await值偏高,可以用blktrace来追踪块设备的I/O,查看存储设备真正处理I/O花费的时间。

4. svctm

iostat里的svctm并不能准确反映存储设备的处理时间,直接忽略。在12.1.2以上版本中已经移除该指标了。

1
Warning! Do not trust this field any more.  This field will be removed in a future sysstat version.

5. 疑问

看到这里,疑问就来了。这么多指标都不准确,我们能够借助iostat观察块设备什么信息?
如果仅仅看单个指标,的确会很容易得出错误的结论。我们将他们放在一起看,还是能够得到许多有用的信息。有助于我们判断当前I/O模型是否合适,压力是否过大,性能瓶颈是否(某块)磁盘。

1
2
3
4
5
6
7
8
9
10
11
    r/s     rMB/s   rrqm/s  %rrqm r_await rareq-sz Device
0.00 0.0k 0.00 0.0% 0.00 0.0k dm-1

w/s wMB/s wrqm/s %wrqm w_await wareq-sz Device
2000.00 7.8M 0.00 0.0% 0.16 4.0k dm-1

d/s dMB/s drqm/s %drqm d_await dareq-sz Device
0.00 0.0k 0.00 0.0% 0.00 0.0k dm-1

f/s f_await aqu-sz %util Device
0.00 0.00 0.33 32.9% dm-1

6. 收集iostat输出脚本

遇到过这么一个需求,需要把iostat的输出保存并转换为excel格式。就是 统计脚本+Excel 可视化iostat的输出,更方便的观察一段时间内磁盘的各项性能指标。
其实已经有工具可以实现了,比如同属于sysstat工具包的sar、sdaf用来收集信息; NMON更是做到了完美可视化。不过有同事习惯了iostat工具,便有了这个需求。

ms_iostat 工具点击下载,使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
./ms_iostat -t 30 -i 10
# 参数说明
# -t,(必须)指定收集时间,单位为分钟
# -i,指定收集间隔,单位为秒,默认为5s
# -r,指定文件保存目录,默认为 /root/mspoc_iostatFile
# -d, 指定需要统计信息的设备,默认全部 /dev/sd* ;比如指定 sda, -d sda ;
# 注意:指定多个设备时,请用 " " 扩起来,比如 -d "sdb sdc sdd sde"
# -v,显示iostat的输出
#
# 如果需要后台执行,使用 '&' ,如下面的格式:
./ms_iostat -t 1000 -i 30 -r /tmp/iostat_file/ &

7. 参考文章

The precise meaning of I/O wait time in Linux
理解 %IOWAIT (%WIO)
纠正几个Linux的IO监控指标的误区
iostat manual page