Linux磁盘I/O详解及常用命令介绍

说实话,谈Linux磁盘I/O,还得从我踩过的坑说起。
当年,我在运维一台旧服务器的时候,硬盘突然开始嘎嘎响,CPU占用率飙升到9 0%以上还卡住。
经排查,发现是某个进程疯狂写入日志,导致机械硬盘成为瓶颈。
这件事让我意识到I/O不应该被当作一个笑话,我需要知道如何去做。

我们先来说一下基本概念。
Linux中的I/O不仅仅是简单的读写,它是一个三层架构。
最上面一层是文件系统层,比如ext4 、XFS等,相当于给硬盘穿了件衣服,这样操作系统就不需要关心底层的细节了。
再往下就是块设备层,这里有CFQ、Deadline等调度算法,决定如何排队。
要知道机械硬盘的寻道时间这么长,随机排队肯定不行。
最底层是设备驱动程序,它直接与硬盘驱动器通信。

必须记住关键指标。
用人类的话来说,吞吐量是每秒可以传输多少MB。
当我测试SSD时,我看到标称值为3 00MB/s。
实际使用时可能只有2 00MB/s。
这称为有效吞吐量。
IOPS就更有意思了,同样是1 000 IOPS,随机读写和顺序读写的性能差别很大,这要看场景。
延迟也是一个障碍,尤其是对于硬盘而言。
寻道加旋转延迟是没有用的。
只看数据传输时间是没有用的。

就常用命令而言,iostat绝对是初学者必学的。
我有一个习惯,安装完服务器后先安装iostat,用-iostat -x1 来观察。
当我看到%util飙升到9 5 %以上的时候,我就知道硬盘要晕在厕所里了。
wait 指标尤为重要。
一般情况下,应该小于svctm。
如果是相反,则说明I/O队列太长。

iotop是一个用于定位“混蛋进程”的神器。
有一次系统突然变慢了。
我使用 iotop 发现这是一个正在疯狂写入磁盘的备份进程。
直接kill掉或者减少线程数,系统立刻起死回生。
不要低估 dd 命令。
测试新SSD时,使用dd if=/dev/zero of=/dev/sda bs=1 G count=1 直接测量写入速度,比那些花哨的测试软件要准确得多。
我还经常使用 hdparm-T​​t/dev/sda 组合,特别是对于服务器硬盘。
我运行-T测试缓存效果,运行-t测试实际读取情况。
可以发现很多问题。

优化这方面,选择正确的文件系统可以省去很多麻烦。
我建议ext4 还是稳定的,支持日志,丢失也可以恢复。
XFS适合写入密集型场景。
比如我的监控系统日志就放在XFS分区。
I/O 调度程序必须根据硬盘类型进行更改。
SSD可以使用deadline,但是HDD则必须使用CFQ。
我见过有人用deadline运行HDD,写操作排队到怀疑人生的地步。
另一个技巧是 O_DIRECT。
我在给一家数据库公司优化的时候,关闭了PageCache,直接使用O_DIRECT读写。
CPU利用率下降了一半,但性能提升却惊人。

在故障排除方面,高延迟是最令人头痛的问题。
有一次我发现await跳到了5 00ms。
我用iotop查了一下,是文件同步过程出了问题,于是改成批量处理,效果立竿见影。
不要等待 SMART如果硬盘出现故障,请向您发出警报。
我的服务器硬盘有坏扇区。
Smartctl-a 显示 Reallated_Sector_Ct 已经有数百个。
我需要赶紧备份数据并更换,不然哪天突然死机就晚了。
您必须小心使用 fsck 命令。
有一次,我强行修复了一个崩溃的分区,结果数据全部丢失,所以最好以单用户模式操作。

说白了,Linux的磁盘I/O并没有那么花哨。
核心是了解三层架构,掌握几个关键命令,知道如何根据场景调整参数。
当年,我就是在不断的踩坑中逐渐获得了这套经验。
现在看这些指标就像看天气预报一样,可以在一定程度上预测问题。

浅淡linux的IO和磁盘IO的检测

磁盘性能压测二三事之——性能参数和指标