iostat 是用来分析 cpu 负载和磁盘 I/O 情况的工具。系统不自带, 安装sysstat 即可。
iostat的数据来源于/proc/diskstats
[[email protected]] ~$ iostat -x
Linux 3.10.0-957.1.3.el7.x86_64 (master-1) 02/01/2019 _x86_64_ (2 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
2.42 0.03 18.52 0.19 0.00 78.84
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.24 0.28 15.06 8.46 125.40 17.45 0.06 4.10 2.68 4.13 0.44 0.67
常用参数:
- x:详细
- m: mb显示
- p:显示磁盘和分区的情况
常用使用方法:iostat -xm 10 5: 每隔10s输出一次,一共输出5次
首先这个百分比是怎么算出来的呢?
比如一秒内有100个cpu时间片,这个cpu时间片就是cpu工作的最小单位。那么这100个cpu时间片在不同的区域和目的进行操作使用,就代表这个区域所占用的cpu时间比。也就是这里得出的cpu时间百分比。
比如下面一个程序:
将文件从磁盘的src位置拷贝到磁盘的dst位置。文件会从src先读取进入到内核空间,然后再读取到用户空间,然后拷贝数据到用户空间的buf上,再通过用户空间,内核空间,数据才到磁盘的dst上。
所以从上面这个程序来看,cpu消耗在kernel space的时候就是sy(系统态使用的cpu百分比),cpu消耗在user space的时候就是us(用户态使用的cpu百分比)。
cpu属性
- %user: 在用户态(用户空间)运行所使用的CPU的百分比.
- %nice:nice操作所使用的CPU的百分比.
- %system:在系统态(内核空间)运行所使用CPU的百分比.
简单说,Kernel space 是 Linux 内核的运行空间,User space 是用户程序的运行空间。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。
Kernel space 可以执行任意命令,调用系统的一切资源;User space 只能执行简单的运算,不能直接调用系统资源,必须通过系统接口(又称 system call),才能向内核发出指令。
str = "my string" // 用户空间
x = x + 2
file.write(str) // 切换到内核空间
y = x + 4 // 切换回用户空间
上面代码中,第一行和第二行都是简单的赋值运算,在 User space 执行。第三行需要写入文件,就要切换到 Kernel space,因为用户不能直接写文件,必须通过内核安排。第四行又是赋值运算,就切换回 User space。
- %iowait:等待输入输出 所使用cpu的百分比。
- %steal: 只对虚拟机有效,表示分配给当前虚拟机的 CPU 时间之中,被同一台物理机上的其他虚拟机偷走的时间百分比。
- %idle:CPU空闲时间百分比。
如果%iowait的值过高,表示硬盘存在I/O瓶颈,%idle值高,表示CPU较空闲,如果%idle值高但系统响应慢时,有可能是CPU等待分配内存,此时应加大内存容量。%idle值如果持续低于10,那么系统的CPU处理能力相对较低,表明系统中最需要解决的资源是CPU。
disk属性
- rrqm/s: 每秒进行 merge(合并) 的读操作数目。即 rmerge/s
- wrqm/s: 每秒进行 merge 的写操作数目。即 wmerge/s
块设备有相应的调度算法。如果两个IO发生在相邻的数据块时,他们可以合并成1个IO。
这个简单的可以理解为快递员要给一个18层的公司所有员工送快递,每一层都有一些包裹,
对于快递员来说,最好的办法是同一楼层相近的位置的包裹一起投递,否则如果不采用这种算法,
采用最原始的来一个送一个(即noop算法),那么这个快递员,可能先送了一个包括到18层,
又不得不跑到2层送另一个包裹,然后有不得不跑到16层送第三个包裹,然后包到1层送第三个包裹,
那么快递员的轨迹是杂乱无章的,也是非常低效的。Linux常见的调度算法有: noop deadline和cfq。此处不展开了。
[email protected]:~# cat /sys/block/sdc/queue/scheduler
[noop] deadline cfq
- r/s: 每秒完成的读 I/O 次数。
- w/s: 每秒完成的写 I/O 次数。
- rsec/s: 每秒读扇区数。read sector
- wsec/s: 每秒写扇区数。
- rkB/s: 每秒读的K字节数。是 rsect/s 的一半,因为每扇区大小为512字节。
- wkB/s: 每秒写K字节数。是 wsect/s 的一半。
- avgqu-sz: average queue,平均请求队列的长度。毫无疑问,队列长度越短越好。
首先我们用超市购物来比对iostat的输出。我们在超市结账的时候,一般会有很多队可以排,
队列的长度,在一定程度上反应了该收银柜台的繁忙程度。那么这个变量是avgqu-sz这个输出反应的,
该值越大,表示排队等待处理的io越多。
- avgrq-sz: 每个IO的平均扇区数,即所有请求的平均大小,以扇区(512字节)为单位,我们经常关心,用户过来的IO是大IO还是小IO,那么avgrq-sz反应了这个要素
对比生活中的例子,超时排队的时候,你会首先查看队列的长度来评估下时间,如果队列都差不多长的情况下,
你就要关心前面顾客篮子里东西的多少了。
如果前面顾客每人手里拿着一两件商品,另一队几乎每一个人都推这满满一车子的商品,你可能知道要排那一队。
因为商品越多,处理单个顾客的时间就会越久。IO也是如此。
- await: 每个IO的平均处理时间(单位是微秒毫秒)。这里可以理解为IO的响应时间,一般地系统IO响应时间应该低于5ms,如果大于10ms就比较大了。这个时间包括了队列时间和服务时间,也就是说,一般情况下,await大于svctm,它们的差值越小,则说明队列时间越短,反之差值越大,队列时间越长,说明系统出了问题。
await = ((所有读IO的时间)+(所有写IO的时间))/((读请求的个数) + (写请求的个数))
注意一点就行了,这个所有读IO的时间和所有写IO的时间,都是包括IO在队列的时间在内的。不能一厢情愿地认为,
是磁盘控制器处理该IO的时间。注意,能不能说,await比较高,所以武断地判定这块盘的能力很菜?
答案是不能。await这个值不能反映硬盘设备的性能。await的这个值不能反映硬盘设备的性能,
await这个值不能反映硬盘设备的性能,重要的话讲三遍。我们考虑两种IO的模型:
250个IO请求同时进入等待队列
250个IO请求依次发起,待上一个IO完成后,发起下一个IO
第一种情况await高达500ms,第二个情况await只有4ms,但是都是同一块盘。但是注意await是相当重要的一个参数,它表明了用户发起的IO请求的平均延迟:
await = IO 平均处理时间 + IO在队列的平均等待时间
因此,这个指标是比较重要的一个指标。
- svctm: 表示平均每次设备I/O操作的服务时间(以毫秒为单位)。如果svctm的值与await很接近,表示几乎没有I/O等待,磁盘性能很好,如果await的值远高于svctm的值,则表示I/O队列等待太长, 系统上运行的应用程序将变慢。
对于iostat这个功能而言,%util固然会给人带来一定的误解和苦扰,但是svctm给人带来的误解更多。
一直以来,人们希望了解块设备处理单个IO的service time,这个指标直接地反应了硬盘的能力。回到超市收银这个类比中,如果收银员是个老手,操作流,效率很高,那么大家肯定更愿意排这一队。
但是如果收银员是个新手,各种操作不熟悉,动作慢,效率很低,那么同样多的任务,就会花费更长的时间。
因此IO的平均service time(不包括排队时间)是非常有意义的。但是service time和iostat无关,iostat没有任何一个参数能够提供这方面的信息。
而svctm这个输出给了人们这种美好的期待,却只能让人空欢喜。从现在起,我们记住,我们不能从svctm中得到自己期待的service time这个值,这个值其实并没有什么意义,
事实上,这个值不是独立的,它是根据其他值计算出来的。既然svctm不能反映IO处理时间,那么有没有一个参数可以测量块设备的IO平均处理时间呢?
很遗憾iostat是做不到的。但是只要思想不滑坡,办法总比困难多,
blktrace这个神器可能得到这个设备的IO平均处理时间。
blktrace可以讲IO路径分段,分别统计各段的消耗的时间。
- %util: 在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度。一般地,如果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘,即使%util是100%,因为磁盘的并发能力,所以磁盘使用未必就到了瓶颈)。
%util 和磁盘设备饱和度
注意,%util是最容易让人产生误解的一个参数。
很多初学者看到%util 等于100%就说硬盘能力到顶了,这种说法是错误的。%util数据源自diskstats中的io_ticks,这个值并不关心等待在队里里面IO的个数,它只关心队列中有没有IO。
和超时排队结账这个类比最本质的区别在于,现代硬盘都有并行处理多个IO的能力,但是收银员没有。
收银员无法做到同时处理10个顾客的结账任务而消耗的总时间与处理一个顾客结账任务相差无几。
但是磁盘可以。所以,即使%util到了100%,也并不意味着设备饱和了。最简单的例子是,某硬盘处理单个IO请求需要0.1秒,有能力同时处理10个。
但是当10个请求依次提交的时候,需要1秒钟才能完成这10%的请求,,在1秒的采样周期里,%util达到了100%。
但是如果10个请一次性提交的话, 硬盘可以在0.1秒内全部完成,这时候,%util只有10%。因此,在上面的例子中,一秒中10个IO,即IOPS=10的时候,%util就达到了100%,
这并不能表明,该盘的IOPS就只能到10,事实上,纵使%util到了100%,
硬盘可能仍然有很大的余力处理更多的请求,即并未达到饱和的状态。下一小节有4张图,可以看到当IOPS为1000的时候%util为100%,
但是并不意味着该盘的IOPS就在1000,实际上2000,3000,5000的IOPS都可以达到。
根据%util 100%时的 r/s 或w/s 来推算磁盘的IOPS是不对的。那么有没有一个指标用来衡量硬盘设备的饱和程度呢。很遗憾,iostat没有一个指标可以衡量磁盘设备的饱和度。
参考文章:
http://bean-li.github.io/dive-into-iostat/
http://linuxperf.com/?p=156
其他io指标
计算方法:每秒采集一次/proc/diskstats
disk.io.ios_in_progress:当前正在运行的实际I / O请求数
disk.io.msec_read:所有读取花费的时间,ms
disk.io.msec_write:所有写入花费的时间 ms
disk.io.msec_total:ios_in_progress> = 1的时间量
disk.io.msec_weighted_total:磁盘花在处理请求上的总加权时间
注意:这个值的意义是『所有请求的总等待时间』
每一次请求结束后,这个值会增加这个请求的处理时间乘以当前的队列长度
如何提高机器的磁盘性能?
1) 首先想到的就是换性能好的磁盘。这个好像是最高效的方式,SSD具有更好的性能,访问数据都是随机的。更小的功耗。LVM(逻辑卷)的扩容。
2) 然后就是Raid (RAID0, RAID1, RAID5, RAID0+1)。通过raid实际数据在多块磁盘的并发读写和数据备份。增强磁盘的可用性和容错能力
3) 确定机器的上线的需求。运维人员一定要知道,机器的使用场景。小文件(占用Inode例如图片)读写瓶颈是磁盘的寻址(tps),大文件(占用磁盘容量)读写的性能瓶颈是带宽
4) Linux有一句话(一切皆文件)。空闲内存作文件系统访问的cache,因此系统内存越大存储系统的性能也越好
5) 最后就是架构层面的优化,CDN(nginx、squid..),机房内部反向代理(squid),memcached,消息队列,缓存机制。总之就是静态的采用缓存机制。非静态的优化性能,减小调用磁盘
哪些问题会导致磁盘缓慢?
1)应用程序设计的缺陷和数据库查询的滥用、操作人员的失误、都有可能导致性能问题
2)性能瓶颈可能是因为程序设计缺陷/内存太小/磁盘有损坏、性能差,但是最终都是CPU耗尽的结果(这就话很实用),系统负载极高,响应迟缓,甚至暂时失去响应。登陆不上机器。
3)由于linux的swap机制。物理内存不够时会使用交换内存(可以调优参数),大量使用swap会带来磁盘I0进而导致CPU消耗
4)可能造成cpu瓶颈的问题:频繁执Perl,php,java程序生成动态web;数据库查询大量的where子句、order by/group by排序……
5)可能造成内存瓶颈问题:高并发用户访问、系统进程多(每个进程都会消耗内存,驻留内存),java内存泄露……
6)可能造成磁盘IO瓶颈问题:生成cache文件,数据库频繁更新,或者查询大表……
如何查看磁盘缓慢?
1)swap(当内存不足时会调用SWAP)
a.si列表示由磁盘调入内存,也就是内存进入内存交换区的数量;
b.so列表示由内存调入磁盘,也就是内存交换区进入内存的数量
c.一般情况下,si、so的值都为0,如果si、so的值长期不为0,则表示系统内存不足,需要考虑是否增加系统内存。或者扩展机器提高可用性
2)IO
a.bi列表示从块设备读入的数据总量(即读磁盘,单位KB/秒)
b.bo列表示写入到块设备的数据总量(即写磁盘,单位KB/秒)
这里设置的bi+bo参考值为1000,如果超过1000,而且wa值比较大,则表示系统磁盘IO性能瓶颈。