在 CPU 看来内存好慢啊,看我跑的多快;在内存看来磁盘你好慢啊,看我比你还快点;磁盘…
IO 问题并非特别常见,但是因为最终要落到磁盘上,当它成为瓶颈时,往往会拖慢你的脚本,今天我们来分析下在 linux 中的 IO 问题
指标
看 IO 并不只是看 IO,记住这句话,因为很多时候,IO 问题总会伴随着别的问题一起出现,而会导致误判的,从而遗漏了问题的关键。
IO 问题的指标来源于两块:
- 文件系统
- 磁盘
iowait
命令
top
iostat
%iowait 表示在一个采样周期内有百分之几的时间属于以下情况:CPU空闲、并且有仍未完成的I/O请求。
指标
iowait 升高或者居高不下,可以考虑存在 IO 瓶颈或压力
rs / ws
命令
iostat -x -d 1
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
vda 0.00 13.00 0.00 4.00 0.00 68.00 34.00 0.00 1.00 0.00 1.00 0.25 0.10
dm-0 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
指标
- r/s: 每秒完成的读 I/O 设备次数。即 rio/s
- w/s: 每秒完成的写 I/O 设备次数。即 wio/s
- rkB/s: 每秒读K字节数。是 rsect/s 的一半,因为每扇区大小为512字节。
- wkB/s: 每秒写K字节数。是 wsect/s 的一半。
从这里可以确定是读或者写存在压力
%util
指标
一秒中有百分之多少的时间用于 I/O 操作,即被io消耗的cpu百分比
如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈
wait
指标
- await: 平均每次设备I/O操作的等待时间 (毫秒)。
- svctm: 平均每次设备I/O操作的服务时间 (毫秒)。
如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;如果 await 远大于 svctm,说明I/O 队列太长,io响应太慢,则需要进行必要优化
排查步骤
对于 IO 问题,其实个人遇到的比较少,因为其实现在大多都是 web 类型的服务应用和一些数据处理服务,基本上都是累垮 cpu 和内存的,但是并不代表 IO 问题就没有,当出现问题的时候就很容易被忽视。(这里暂时不讨论网络的 IO 问题,关注于磁盘)
- 确定当前应用存在 IO 操作:有很多时候你自己都不知道你的应用存在 IO 操作,如:日志操作,临时文件…
- 确定 iowait :这个指标很关键,虽然它高不一定 100% 有问题,但是能证明存在了大量的 IO 操作
- 使用 iostat 看:如果确定了前两项,那么就可以考虑 IO 可能存在瓶颈,就可以看一下读写大不大是否正常
- 使用 pidstat -d 看:确定是否是自己进程导致,还是别的应用或者是中间件导致
- 最后看到底是谁在操作并且操作了什么文件:strace lsof 基本就能分析出最终的一个文件操作了
问题原因
日志打印
这个是最常见的一个问题,大多数情况下,日志的打印基本都是异步的一个操作,并且日志大多数情况下也比较小。但代码是人写的,所以就会出现问题。
最常见的是,将返回值直接输出到日志,有的时候,一些命令的调用或者是一些请求的返回,当出现异常时错误输出可能会很大,而直接输出到日志那么势必会增加 IO 负担。而当出现错误程序员必然会将错误打印日志。而出现错误必然会导致用户重试。
用户重试 -> 命令出错 -> 打印错误日志 -> 用户重试
一方面我见过直接日志把磁盘吃满的情况,一方面还有因为日志开启了 debug 导致其他 IO 等待的问题
临时文件
我们在执行命令或者是利用磁盘做缓存,或者是文件上传,都会产生一些临时文件,而这些临时文件的操作也有可能导致 IO 问题
中间件
mysql 、mongo、redis等等一下常见的组件都会对磁盘进行操作,尤其是数据库这种,存储数据量很大的情况。注意 IO 问题并不一定是写,有可能是读! 因为你数据存磁盘上,你要进行读取,磁盘的磁头也就扫那么快,要不你就 SSD,否则当读取量很大的时候,那也有可能导致瓶颈
direct
有的时候也和我们操作 IO 的方式有关,如果我们之间跳过系统缓存直接操作磁盘。还有随机写,同步异步也会直接影响 IO 的速度
硬件
虽然这个很不常见,对于我们来说还是很少看到,但不得不提一下,凡是有万一嘛。
最直接的就是磁盘换 ssd,使用 RAID….
如果硬件出现问题,那么可以尝试看看 dmsg 看看是否有出现一些奇怪的报错信息。
总结
就想一开始说的,I/O 往往是一个系统中跑的最慢的,如果它出现瓶颈,那么势必带来的问题就很明显。
同样的,也就是因为是最后一个位置,在这之前都可以通过CPU、内存、缓存等等在这之前搞定它。
如果你的数据最后落库,那么数据库上的 I/O 问题也是需要被考虑在内的。