说明

%iowait, await, %util 是用来衡量硬盘负载的三个指标, 但是这几个指标通常容易被误解, 实际上, 这三个指标单纯的高, 并不一定能说明相应的磁盘有问题或者有瓶颈, 而是需要结合具体执行 IO 操作的程序的执行方式, 综合的来判断指标高的原因.

关于 await, %util 的计算方式可以参照:
linux iostat 输出详解

总结

%iowait:

最容被误解的参数, 实际上这是一个非常宏观的系统指标, 其表示 "CPU空闲 并且 有未完成的IO " 这种状态在一个采样周期里的占比, 一般来说当一个进程进行同步的 IO 操作时, 进程将会被挂起, CPU 将会空闲, 等待 IO 完成, 这时候如果没有其它进程占用 CPU 此时的状态将会被计入 iowait 的统计时间以内. 但是 CPU 空闲也只是当前进程空闲, 空闲出来的 CPU 是可以进行其它操作的, 如果此时 %iowait 较高, 只能说明在等待 IO 完成的时间里系统没有其它进程来占用 CPU 了, 而 IO 未完成, 有可能只是单纯的 IO size 比较大, 完成需要较长时间, 并不一定是 IO 有问题.

而且如果等待 IO 完成时系统有其它繁忙的进程占用了 CPU, 那么无论此时 IO 完成时间多长(即使是IO完全卡死), %iowait 也会非常的低, 因为此时CPU不空闲了, 因为 %iowait 只是反映 "CPU空闲 并且 有未完成的IO " 这种状态时间的占比, 两个条件缺少一个都不会计入 iowait 的时间.

await

每个I/O的平均耗时, 包括在内核 IO 队列内的时间和在存储设备上执行此 IO 的时间, 所以 await 高可能有两个原因, 一是 IO 在 IO queue 里耗时较长, 另一个就是由于 IO 在存储设备上执行的时间比较长, 而 IO 在 IO queue 里耗时较长可能是由于程序一次并发了过多的 IO, 让 IO 在 queue 排队, IO 在存储设备上执行的时间比较长也有可能时 IO 本身就比较大, 例如在硬盘上写 1KB 文件, 耗时一定是比 1MB的时间短的, 所以 await 高, 还要结合业务本身的特点判断 await 高的原因

%util

这个反映 IO queue, 中存在 IO 在采样周期里的占比, 只要 IO queue 中存在 IO, 就会被计入到 %util 的时间内, 无论是 1 个 IO 或者 100 个IO, 并且也只计算 IO 存在于 queue 里面的时间, 所以此时即使磁盘压力较大, 但是 IO queue 中并没有排队的 IO 那么 %util 也不会高(例如每次 IO size 都比较大), 或者有些程序进行顺序 IO, 完成几个再发下一个, 并且 IO size 并不大, 此时即使磁盘压力较小 %util 也会比较高

测试

环境和命令

使用 fio 模拟客户端, 通过不同的 fio 引擎和不同的队列深度配置来模拟顺序的和并发的 IO

环境如下

[root@centos-76-c1~]# uname -a
Linux centos-76-c1 5.5.7-1.el7.elrepo.x86_64 #1 SMP Fri Feb 28 12:21:58 EST 2020 x86_64 x86_64 x86_64 GNU/Linux
[root@centos-76-c1~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root@centos-76-c1~]# fio --version
fio-3.1

使用 iostat -mx 1 10000 sdb 来模监控 %iowait, await , %util 具体数值

[root@centos-76-c1~]# iostat -mx 1 10000 sdb
Linux 5.5.7-1.el7.elrepo.x86_64 (centos-76-c1) 03/05/2020 _x86_64_ (1 CPU) avg-cpu: %user %nice %system %iowait %steal %idle

1.46 0.00 0.78 12.33 0.00 85.43 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.66 0.60 263.41 0.01 1.17 9.20 21.27 81.06 7.02 81.23 0.16 4.23 avg-cpu: %user %nice %system %iowait %steal %idle

0.00 0.00 0.00 0.00 0.00 100.00 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 ......

%iowait

%iowait 与 CPU 本身的关系

找一个 CPU 空闲的时期

[root@centos-76-c1~]# top -n 1
top - 17:38:33 up 1:02, 3 users, load average: 0.00, 0.10, 0.12
Tasks: 136 total, 1 running, 81 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 977804 total, 696812 free, 105696 used, 175296 buff/cache
KiB Swap: 1572860 total, 1572860 free, 0 used. 697424 avail Mem

随便增加一些负载差不多的普通负载, 观察此时的 iowait

[root@centos-76-c1~]# fio --name=randwrite --rw=randwrite --bs=16k --size=1G --runtime=60 --ramp_time=20 --ioengine=sync --numjobs=1 --filename=/dev/sdb --direct=1 --group_reporting
randwrite: (g=0): rw=randwrite, bs=(R) 16.0KiB-16.0KiB, (W) 16.0KiB-16.0KiB, (T) 16.0KiB-16.0KiB, ioengine=sync, iodepth=1
fio-3.1
Starting 1 process
Jobs: 1 (f=1): [w(1)][100.0%][r=0KiB/s,w=1472KiB/s][r=0,w=92 IOPS][eta 00m:00s]
randwrite: (groupid=0, jobs=1): err= 0: pid=7724: Thu Mar 5 17:56:42 2020
write: IOPS=86, BW=1390KiB/s (1423kB/s)(81.5MiB/60004msec)
clat (usec): min=2917, max=48358, avg=11505.79, stdev=4808.19
lat (usec): min=2918, max=48359, avg=11506.34, stdev=4808.19
.....

iowait 达到了 99%

......
avg-cpu: %user %nice %system %iowait %steal %idle
0.00 0.00 1.00 99.00 0.00 0.00 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.00 0.00 101.00 0.00 1.58 32.00 0.94 9.86 0.00 9.86 1.02 10.30 avg-cpu: %user %nice %system %iowait %steal %idle

0.00 0.00 0.00 100.00 0.00 0.00 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.00 0.00 97.96 0.00 1.53 32.00 0.97 10.41 0.00 10.41 1.02 10.00

......

此时增加一个十分耗费 CPU 的计算圆周率的命令, 计算 50000 位的圆周率

[root@centos-76-c1~]# time echo "scale=50000; 8*a(1)" | bc -l -q
  • 1

此时 CPU 利用率已经非常高

[root@centos-76-c1~]# top -n 1
top - 17:59:21 up 1:22, 3 users, load average: 0.21, 0.17, 0.09
Tasks: 138 total, 2 running, 81 sleeping, 0 stopped, 0 zombie
%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 977804 total, 696652 free, 105816 used, 175336 buff/cache
KiB Swap: 1572860 total, 1572860 free, 0 used. 697288 avail Mem
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这是可以看到 %iowait 直接变成了 0.00

......
avg-cpu: %user %nice %system %iowait %steal %idle
100.00 0.00 0.00 0.00 0.00 0.00 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.00 0.00 66.00 0.00 1.03 32.00 0.66 10.48 0.00 10.48 1.98 13.10 avg-cpu: %user %nice %system %iowait %steal %idle

99.01 0.00 0.99 0.00 0.00 0.00 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.00 0.00 69.31 0.00 1.08 32.00 0.66 10.11 0.00 10.11 2.00 13.86

......

总结

通过上面的测试可以证明 %iowait 是一个十分宏观的一个参数, 系统其他服务对 CPU 的利用会直接影响这个数值, 如果 CPU 利用率够高, 即使此时 IO 完全卡死, 此时 %iowait 可能也很低. %iowait 即使很高, 实际上硬盘的压力可能也不大.

await

await 和 iodepth 的关系

使用 fio 模拟客户端, 固定大小的 io 请求, 通过配置不同的 --iodepth= --iodepth_batch_submit= --iodepth_low= 来实现不同并发度的 IO

[root@centos-76-c1~]# fio --name=randwrite --rw=randwrite --bs=4k --size=1G --runtime=60 --ramp_time=20 --ioengine=libaio --iodepth=<iodepth> --iodepth_batch_submit=<iodepth> --iodepth_low=<iodepth>  --numjobs=1 --filename=/dev/sdb --direct=1 --group_reporting
  • 1
测试结果
iodepth IOPS BW avgqu-sz await
1 90 363KiB/s 0.20 3.03
4 337 1349KiB/s 2.17 6.51
16 1168 4676KiB/s 10.00 7.50
64 1828 7317KiB/s 47.97 18.33
256 1851 7424KiB/s 252.03 300 ~ 500
1024 1723 6963KiB/s 270.84 300 ~ 600
总结

随着并发度越来越高, 达到了本机 IO 能承受的 IO 的上限, 大量 IO 在存储集群里面排队, 可以看到 await 随着 IO 在队列中排队时间的增大而逐渐增大

await 和 iosize 的关系

使用 fio 模拟客户端, 固定大小的 io iodept, 通过配置不同的 --bs=<block_size> 来实现不同<block_size>的 IO (block_size 即一次读写的文件的大小)

[root@centos-76-c1~]# fio --name=randwrite --rw=randwrite --bs=<block_size>  --size=1G --runtime=60 --ramp_time=20 --ioengine=libaio --iodepth=1 --iodepth_batch_submit=1 --iodepth_low=1  --numjobs=1 --filename=/dev/sdb --direct=1 --group_reporting
  • 1
测试结果
block_size IOPS BW avgrq-sz avgqu-sz await
4KiB 90 364KiB/s 8.00 0.25 2.93
16KiB 69 1120KiB/s 32.00 0.64 9.75
64KiB 30 1948KiB/s 128.00 0.84 30.11
256KiB 11 3004KiB/s 512.00 0.93 89.90
1MiB 4 4168KiB/s 2048.00 1.14 227.00
4MiB 1 4531KiB/s 2048.00 - 2560.00 3.46 902.75
16MiB 0 5206KiB/s 2048.00 - 2560.00 12.50 2223.40
总结

可以看到随着 block_size 即 一次读写的文件的大小不断增加, await 也逐渐增加, 实际上此时 IO 并不能说 IO 是瓶颈, 或者 IO 延时过高, 只是单纯的完成大 IO 耗时更长

%util

%util 与 IO 的关系

使用 fio 分别测试不同 iosize 的同步 IO

[root@centos-76-c1~]# fio --name=randwrite --rw=randwrite --bs=4K --size=1G --runtime=60 --ramp_time=20 --ioengine=sync --numjobs=4 --filename=/dev/sdb --direct=1 --group_reporting --sync=1
randrw: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=sync, iodepth=1
...
fio-3.1
Starting 4 processes
Jobs: 2 (f=2): [E(0),w(4)][100.0%][r=0KiB/s,w=1081KiB/s][r=0,w=270 IOPS][eta 00m:00s]
randrw: (groupid=0, jobs=4): err= 0: pid=8310: Thu Mar 5 19:24:57 2020
write: IOPS=292, BW=1169KiB/s (1197kB/s)(68.5MiB/60004msec) ......
......
Davg-cpu: %user %nice %system %iowait %steal %idle
100.00 0.00 0.00 0.00 0.00 0.00 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.00 0.00 325.00 0.00 1.27 8.00 2.17 7.18 0.00 7.18 1.17 38.10 avg-cpu: %user %nice %system %iowait %steal %idle

99.00 0.00 1.00 0.00 0.00 0.00 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.00 0.00 309.00 0.00 1.21 8.00 2.28 7.87 0.00 7.87 1.08 33.40

......
[root@centos-76-c1~]# fio --name=randwrite --rw=randwrite --bs=1m --size=1G --runtime=60 --ramp_time=20 --ioengine=sync --numjobs=4 --filename=/dev/sdb --direct=1 --group_reporting --sync=1
randwrite: (g=0): rw=randwrite, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=sync, iodepth=1
...
fio-3.1
Starting 4 processes
Jobs: 3 (f=3): [w(3),_(1)][58.2%][r=0KiB/s,w=4096KiB/s][r=0,w=4 IOPS][eta 00m:59s]
randwrite: (groupid=0, jobs=4): err= 0: pid=8396: Thu Mar 5 19:32:23 2020
write: IOPS=4, BW=4407KiB/s (4513kB/s)(261MiB/60647msec)
clat (msec): min=406, max=1552, avg=928.17, stdev=188.99
lat (msec): min=406, max=1552, avg=928.21, stdev=188.99
......
......

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util

sdb 0.00 0.00 0.00 5.00 0.00 5.00 2048.00 3.77 753.40 0.00 753.40 2.00 1.00 avg-cpu: %user %nice %system %iowait %steal %idle

99.01 0.00 0.99 0.00 0.00 0.00 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sdb 0.00 0.00 0.00 3.96 0.00 3.96 2048.00 3.40 860.50 0.00 860.50 2.00 0.79
    <>/ul>

总结

可以看到当 IO size 较小时, 硬盘即使压力不大( sdb 为 ssd ) %util 也达到了 30% , 后来当 IO size 为 1M 时磁盘实际负载并不会比之前低, 但是 %util 却很低, 这与要是由于不同 size 的 IO 造成内核 IO queue 里面停留时间不同造成的, 和硬盘本身的负载并没有直接的关系

[转帖]磁盘负载指标 %iowait, await, %util 的正确理解的更多相关文章

  1. [转帖] 磁盘IOPS 简介 -- 虽然自己知道有这么一回事 但是自己还是没有系统的总结.

    来源: https://www.cnblogs.com/zengkefu/p/5634299.html 机械硬盘的连续读写性很好, 但随机读写性能很差.这是因为磁头移动至正确的磁道上需要时间,随机读写 ...

  2. 系统一般信息监控查看shell.磁盘,负载等达阀值告警机制,改进测试中.

    1 #!/bin/sh  2 #Create by Qrui  3 while [ "1"="1" ]  4 do  5 clear  6  7 echo &q ...

  3. linux 磁盘io利用率高,分析的正确姿势

    一.背景简介 作为一个DBA难免不了会遇到性能问题,那么我们遇到性能问题该如何进行排查呢?例如我们在高并发的业务下,出现业务响应慢,处理时间长我们又该如何入手进行排查,本片文章将分析io高的情况下如何 ...

  4. java.util.Random深入理解

    java.util.Random next方法的原理 比较好的参考文档: http://isky001.iteye.com/blog/1339979 package random.utilrandom ...

  5. await异步的,容易理解一点

    C# 5.0中引入了async 和 await.这两个关键字可以让你更方便的写出异步代码. 看个例子: public class MyClass { public MyClass() { Displa ...

  6. Apache反向代理结合Tomcat集群来实现负载均衡(一)、概念理解

    好的博文一般都能做到"望题知文",看下标题就知道下边要讲的内容,写这个标题时犹豫了一下,本来要将标题定位apache+tomcat实现负载均衡,但是又认为这样显得比較模糊.后来想了 ...

  7. C# async/await异步编程深入理解

    异步函数简介 一般指 async 修饰符声明得.可包含await表达式得方法或匿名函数. 声明方式 异步方法的声明语法与其他方法完全一样, 只是需要包含 async 关键字.async可以出现在返回值 ...

  8. wait notify notifyAll await signal signalAll 的理解及示例

    从常见的一道面试题开始,题目的描述是这样子的: 有三个线程分别打印A.B.C,请用多线程编程实现,在屏幕上循环打印10次ABCABC- 网上大都教了你怎么去实现,其实我也写过一篇 https://bl ...

  9. 对于异步编程Await和Async的理解

    public class AsyncInSync { /// <summary> /// 同步代码里有异步代码 /// /// /// 结果 /// Main Thread Before ...

  10. iostat -x 1 查看磁盘的IO负载

    Linux系统出现了性能问题.一般我们能够通过top.iostat,vmstat等命令来查看初步定位问题.当中iostat能够给我们提供丰富的IO状态数据 $ iostat -x -1  avg-cp ...

随机推荐

  1. MySQL篇:第六章_详解mysql视图

    周末有朋友来上海没来得及更新,特此更两篇以正身 视图 含义:理解成一张虚拟的表 视图和表的区别: 使用方式 占用物理空间 视图 完全相同 不占用,仅仅保存的是sql逻辑 表 完全相同 占用 视图的好处 ...

  2. 云小课|DSC帮您管数据,保障您的云上数据安全

    摘要:华为数据安全中心,积累华为云多年数据经验,整合云上各类数据源,搭载数据安全黑科技,通过深度行为识别引擎,助您轻松管理云上数据. 本文分享自华为云社区<云小课 | DSC帮您管数据,保障您的 ...

  3. 带你认识三种kafka消息发送模式

    摘要:在kafka-0.8.2之后,producer不再区分同步(sync)和异步方式(async),所有的请求以异步方式发送,这样提升了客户端效率. 本文分享自华为云社区<kafka消息发送模 ...

  4. 【终极教程】Cocos2dx服务端重构(优化cocos2dx服务端)

    [终极教程]Cocos2dx服务端重构(优化cocos2dx服务端) 文章目录 概述 问题概述1. 代码混淆代码加密具体步骤测试和配置阶段IPA 重签名操作步骤2. 缺乏文档3. 缺乏推荐的最佳实践4 ...

  5. 火山引擎A/B测试:MAB智能调优实验,企业活动效果提升新利器

      618临近,各大电商APP的预热活动已然拉开序幕.对企业而言,一场活动从策划到上线,中间经过效果验证,其业务成本很高.一个好的活动创意从策划.开发.到最终发布,至少会经历几周实践,如果中间还经历A ...

  6. PPT 年终总结PPT 应该怎么样改

  7. Hugging News #0609: 最新代码生成模型 StarCoder+ 和 StarChat Beta 重磅发布!

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...

  8. Grafana--变量(label_values)

    grafana官方文档:https://grafana.com/docs/grafana/latest/ 版本:6.5.2 模板与变量(摘抄自官方文档): 变量是值的占位符.您可以在度量查询和面板标题 ...

  9. 批量上传 jar 包到远程 maven 仓库

    mvn deploy命令: mvn deploy:deploy-file -Dmaven.test.skip=true -Dfile=log-lib-1.1.jar -DgroupId=com.sun ...

  10. <vue 基础知识 9、v-model使用 input、radio、checkbox、select、修饰符>

    代码结构 一.     01-v-model的基本使用 Vue中使用v-model指令来实现表单元素和数据的双向绑定 1.效果 2.代码 01-v-model的基本使用.html <!DOCTY ...