不奢望岁月静好 只希望点滴积累

0%

理解IO_WAIT--IO性能到底怎么回事儿

应用系统的大部分瓶颈在IO上、不是所有的问题都可以利用内存或者CPU Cache做缓存解决、Mysql单表几千万的数据、早已不是罕见现象了、意味着, 使用内存当缓存、存储空间是不够用的. 大部分请求还是会打到硬盘上.

IO性能、顺序和随机访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
从硬盘厂商的性能报告上、通常可以看到两个指标: 响应时间(Response Time)和数据传输率(Data Transfer Rate)

现在常用的硬盘有两种: HDD硬盘(机械硬盘) 和 SSD硬盘(固态硬盘). 现在的HDD硬盘使用的是 SATA 3.0 的接口.
SSD硬盘有两种接口: SATA 3.0 和 PCI Express 接口

SATA 3.0 接口、带宽是6Gb/s, b是bit、相当于每秒传输 768M 数据; 日常使用的HDD硬盘的数据传输率差不多200MB/s
SSD的硬盘、数据传输率差不多500MB/s, 实际SSD的硬盘可以更快. 可以换用PCI Experss的三星SSD硬盘、
它的数据传输率、在读取的时候可以达到2GB/s 左右、差不多是HDD硬盘的10倍、写入时也有1.2GB/s.

除了数据传输率、我们还关心响应时间. SSD硬盘大概在几十微秒、HDD大概在几ms到十几ms、差异在几十倍甚至上百倍.

单看响应时间和吞吐率、硬盘性能还可以、基本上在ms时间内可以返回, 1s内可传输的数据也有200MB左右、
db一条记录、一般也就1kb大小、差不多每秒可写入 200M*1024 / 120w条数据、似乎和平时经验不符 ?

因为硬盘顺序读写和随机读写的性能差异很大.
SSD随机读写的时候、数据传输率只有40MB/s、只有顺序读写情况的几十分之一、按照每次读取4KB计算、
40MB/s / 4kb = 10000次、即: 每秒随机读取1万次、写入会多一些、1s大概90MB、即: 2w多次
这个每秒读写的次数、称为IOPS、即: 每秒输入输出操作的次数

HDD的IOPS通常只有100左右、而不是20w次、这个100怎么得到的呢 ?如何优化 ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
一块机械硬盘由盘面、磁头和悬臂三个部件组成.
盘面: 就是实际存储数据的盘片、通常是使用铝、玻璃或者陶瓷制成的光滑盘片, 盘面有一层磁性涂层
数据就存储在磁性的涂层上、中间有一个受电机控制的转轴, 用来控制盘面旋转.

硬盘一个很重要的指标是转速, 通常有5400转、7200转、10000转的、这个转速指的就是转轴的旋转速度、
英文单位 RPM, 即: 每分钟的旋转圈数、7200转为例, 折算到s、就是120

磁头: 数据是通过磁头从盘面读取、然后通过电力信号传输给控制电路、接口、再到总线的
通常一个盘面在正反两面有连你刚刚磁头、且: 一块硬盘也不是只有一个盘面、而是上下堆叠了很多个盘面、
各个盘面是平行的、每个盘的正反两面都有磁头.

悬臂: 连接在磁头上、在一定范围内把磁头定位到某个特定的磁道上.

盘面通常是圆形的、多个同心圆组成、每个磁道有自己的编号, 悬臂用来控制读哪个磁道的数据
磁道会分成一个个扇区、上下平响的一个个盘面的相同扇区叫一个柱面、

读取数据分两步:
1. 将盘面旋转到某一个位置、在这个位置上、悬臂可以定位到整个盘面的任意子区间、这个区间称为`几何扇区`
2. 将悬臂移动到特定磁道的特定扇区、找到之后磁头落下、读取数据
所以, 需要的时间也由两个部分构成:
1. 平均延时, 就是将几何扇区对准悬臂的时间
7200转为例, 1s可以旋转240个半圈、即: 1s/240 = 4/71ms
2. 平均询道时间, 即 悬臂定位到扇区的时间
HDD硬盘一般在4-10ms、
这样随机数据访问延时一般在8-14ms, 那么
1s/8ms = 125 IOPS 或者 1s/14ms = 70 IOPS

硬盘物理结构.png

如何定位 IO_WAIT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
由上边可以看到、即使是PCI Express接口的SSD硬盘、IOPS也只有2w左右, CPU 的主频通常在2GHZ以上、
也就是每秒可以做20亿次操作. 即使一条指令需要多个时钟周期、一秒内CPU可执行的指令数和硬盘能进行的操作次数
也有好几个数量级的差异, 所以常听到性能瓶颈在IO上的说法、因为CPU发出指令之后、需要等待IO操作完成.

如何判断程序性能问题是否真的来源于IO瓶颈呢 ?
1. top指令
top指令的输出结果中、有一行 %CPU 开头、有一个 wa 的指标、就代表iowait, 即: CPU等待io操作完成花费的时间占CPU的百分比

iostat可以看到实际的情况

avg-cpu: %user %nice %system %iowait %steal %idle
17.02 0.01 2.18 0.04 0.00 80.76
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 1.81 2.02 30.87 706768 10777408

tps: 对应的就是硬盘的 IOPS 指标
KB_read/s 和 kb_write/s 对应的就是 数据传输指标
iotop 可以看到具体哪一个进程占用了大量的io