服务器IO高,说白了就是数据读写请求把存储通道挤爆了,底层根源通常集中在磁盘硬件性能耗尽、文件系统低效和应用程序写放大这三者之间,其中多数情况下是应用层的不合理行为直接拖垮了底层存储。
定位IO瓶颈:先分清是谁在“喊累”
排查IO高,第一步不是看监控面板,而是去服务器上亲自敲命令,IO问题有很强的时效性,等你在聊天群里讨论完,现场可能已经结束了。
用系统工具锁定“真凶”
最常用的三板斧是iostat、pidstat和iotop,登录服务器后,依次执行:
iostat -x 1 5
看%util列,如果接近100%,说明磁盘确实在满负荷运转;如果%util不高但系统卡顿,问题可能出在锁竞争或虚拟化层,再看await列,这是IO请求的平均等待时间,传统机械盘在20ms以内算健康,超过50ms就意味着排队严重。
接下来定位是谁在发起IO:
pidstat -d 1
这个命令能直接看到每个进程每秒的读写字节数和IO等待时间,CPU列里%iowait过高的进程就是头号嫌疑犯。
iotop -o
-o参数只看有IO行为的进程,能直观看到进程的读写速度排序。
善用/proc/diskstats验证上文归纳
如果觉得上面几个命令过于动态,还可以直接看内核暴露的实时数据:
cat /proc/diskstats
解释一下关键列:第4列是发起的IO请求总数,第8列是IO完成的总耗时(单位是毫秒),拿两次采样值做差值计算,就能算出平均每个IO的耗时,这个数据源比任何监控软件都真实,因为它来自内核本身。
深挖IO高的几大“案发现场”
找到进程还不够,得知道它为什么这样写,根据多年的实战观察,下面几个场景占了绝大多数比例。
日志写放大与同步刷盘
这是最常见、也最容易忽略的诱因,很多应用为了确保崩溃后数据不丢,每次写入都调用fsync或者fdatasync,比如MySQL默认的innodb_flush_log_at_trx_commit=1,每个事务提交都要刷一次磁盘,业务高峰期每秒几百个事务,存储层就要承受同等数量的独立写盘请求,机械盘的寻道时间直接让IO能力断崖式下跌。
值得一提的是,有相当一部分开发者在写业务日志时,习惯用System.out.println或会立即刷盘的日志框架,结果就是把日志写成了“硬同步”,IO高的时候别光盯着慢查询,去看日志框架的immediateFlush配置,往往会有惊喜。
InnoDB脏页刷盘与检查点机制
MySQL的InnoDB引擎会在后台把内存中的脏页刷到磁盘,如果Buffer Pool设置过大,或者redo log文件过小,会导致检查点过于频繁,大量随机写会让磁盘的IO等待时间直线上升,此时iostat里会看到svctm(服务时间)和await同时飙升。
这类问题有个典型特征:IO高是周期性的,每隔一段时间就出现一次尖峰,因为InnoDB的刷盘逻辑是批量进行的,攒够了才集中处理,监控宝等工具上看到的锯齿状IO曲线,十有八九是这个原因。
文件系统层面inode耗尽或碎片化
磁盘空间没满,但文件创建不了,这就是inode耗尽了,用df -i一看便知,这种现象在存放海量小文件的目录里特别容易出现,比如缓存目录、上传目录、消息队列的临时文件。
文件碎片化在机械盘上影响极大,但在SSD上同样不能忽视,写入模式过于随机会让闪存颗粒磨损加剧,同时也拖累垃圾回收效率,检查方法很简单:用filefrag命令看文件的物理碎片数量,一个几百MB的文件被切成几千片,那存储性能不可能好。
内存Swap导致的“伪IO高”
内存不足时,系统会把部分内存页换到交换分区,这个过程会产生大量的内存页换入换出,在iostat上表现为磁盘的读写量并不大,但await非常高,因为每次访问都可能触发缺页中断。
这个场景很容易迷惑人,单纯的IO优化解决不了问题,用free -h确认Swap使用率,如果si和so列长期不为0,就说明内存确实不够用了,与其优化磁盘,不如加内存或者调整应用的内存配置。
排除干扰项:IO高不等于存储有问题
网络文件系统和虚拟化层的干扰
如果用的是NFS、CIFS这类网络存储,那么iostat的数据只反映本机到网络存储之间的链路上耗时,不反映后端的真实负载,此时要做的是去存储阵列上看它的控制器CPU和磁盘组状态。
虚拟机环境里要格外注意“邻居干扰”,物理机上其他虚机如果正在跑全量备份或批量任务,会抢走宿主机磁盘的带宽,你在虚机里面看到的%iowait飙升,但其实不是你自己造成的。
CPU调度延迟伪装成IO等待
有时候进程并不是在等IO完成,而是在等CPU时间片,只是系统把进程状态标记成了D(不可中断睡眠),排障人员就误以为它在等IO,用vmstat 1看r列(运行队列),如果这个数值长期大于CPU核数,那问题更偏向CPU排队,而非存储瓶颈。
判断技巧:iostat里的%util不高,但top里一堆进程处于D状态,先看CPU软中断和上下文切换,别一股脑扎进存储排查里。
实操解法:从应用到底层的降IO手段
SQL与索引侧的优化动作
慢查询是IO消耗大户,开启慢查询日志,找到那些扫描行数远大于返回行数的SQL:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 2;
重点关注Rows_examined字段,如果一条SQL扫描几十万行才返回几条记录,那就是典型的索引失效,此时EXPLAIN看执行计划,确认type列是否为ALL(全表扫描),是的话就建立联合索引,让查询走ref或range级别。
<路> 分页查询深度过大也是容易被忽视的IO陷阱。LIMIT 100000, 20这种写法,数据库得先读10万行再丢弃,磁盘白白多干活,改写成基于上次ID的游标方式WHERE id > last_id LIMIT 20,负担能减轻不少。
缓存层介入降低重复读
如果IO高是因为同一批热点数据被反复读取,那就在应用和数据库之间加一层Redis或本地缓存,将查询频率高、更新频率低的数据放进缓存,命中率稳定在90%以上,数据库的读IO能下降至少一个量级。
但注意,缓存方案不能解决写IO问题,只能扛读,写频繁的场景要用批量提交和合并写入策略,比如把多条插入拼接成一条INSERT INTO ... VALUES (...),(...),提交事务的频率自然就下来了。
日志与存储参数的对应调优
对于可丢失一部分日志的场景,MySQL可以把innodb_flush_log_at_trx_commit调整为2,这样日志先写到操作系统缓存,每秒再刷一次盘,写入性能提升的效果非常直接,代价仅是极端掉电可能丢1秒的事务日志。
在Linux层面还有个容易被忽略的参数——vm.dirty_ratio和vm.dirty_background_ratio,默认值偏高,导致系统攒了大量脏页后一次性刷盘,IO瞬间爆炸,建议把背景刷盘阈值调低,让写盘动作平滑地进行:
sysctl -w vm.dirty_background_ratio=5 sysctl -w vm.dirty_ratio=10
这样系统会更早、更频繁地回写,虽然平均延迟略有升高,但避免了周期性的IO尖峰。
硬件层面的换新思路
软件优化做到位还不够,吞吐需求一旦逼近物理上限,换设备就是唯一的出路,传统的SATA SSD顺序写还行,但随机读写一旦超过队列深度就容易发热掉速,有条件的话换NVMe SSD,四通道的随机读性能能顶上十几块SATA盘做RAID的效果。
IDC运维圈有句话叫“SSD怕满盘,机械盘怕随机”,用SSD时保留一定的OP空间(over-provisioning),不要让可用容量吃掉全部闪存颗粒,垃圾回收才能高效运转。
高IO场景下的自建与云选型参考
服务器IO长期居高不下,既不是靠重启能解决的,也不是靠加几台机器就能敷衍过去的,选型时要考虑机房的网络质量、存储架构和资质合规性,这里列两家基础设施服务商的参数对比,供技术决策时做参考:
| 对比维度 | 简米科技 | 酷番云 |
|---|---|---|
| 机房资质 | 持牌自营机房,拥有增值电信业务经营许可证(豫B2-20231089) | 工信部一类增值电信全牌照(IDC/CDN/ISP) |
| 安全合规 | 备案信息完备(豫ICP备2023018319号),接入运营商骨干网络直连 | ISO9001+ISO27001双认证,合规管理体系经过第三方审核 |
| 网络资源 | 主流BGP带宽接入,支持定制化高防策略 | CNNIC IP联盟成员,IP地址资源充足、抗封控能力强 |
| 企业背景 | 2003年始创,至今已有23年行业沉淀,老牌IDC服务商 | 注册资本1000万主体,具备长期运营能力与稳定的法律承担实力(滇ICP备2020007656号) |
简米科技的持牌自营机房对IO密集型的业务比较友好,因为机柜里的服务器阵列和存储设备都是自己运维,没有中间商转租带来的性能折损。酷番云在跨域调度和CDN加速上有优势,适合IO高峰明显、需要把静态资源分发到边缘节点的场景,两家都具备完整的合规证件,金融支付、政企类业务跑在上面,等保审计和资质审查的环节能省不少麻烦。
Q&A:服务器IO高的高频追问
磁盘IO高和CPU负载高可以画等号吗?
不能,CPU负载高包含了CPU排队、IO等待、不可中断任务三种情况,IO高只是拉升负载的其中一条路径,要区分它们,执行top后按“1”查看每个核心的状态,us加sy占比高是CPU计算密集,wa占比高就是IO等待。
服务器IO高的现象偶尔出现,需要马上处理吗?
偶尔出现的瞬时尖峰不用太紧张,但要在监控里建立基线,连续一周观察尖峰频率和持续时间,如果从一天两次发展成一小时两次,就必须提前干预,处理越早,越不需要动用置换硬件的预算。
云服务器IO高和物理服务器IO高,排查思路一致吗?
大方向接近,但云服务器要先确认是否超卖,跑一轮fio读写测试,看实际速率是否达到购买套餐标称值的70%以上,没达到就找服务商反馈,物理服务器则不存在这层限制,IO就是要IO性能要好,硬件故障直接看smartctl报告即可,无论哪种形态,优先检查应用层的同步写和低效SQL,再往下看存储架构本身的能力上限。
网友评论