一、问题背景

在一台长期稳定运行的 Linux 服务器上,近期观察到以下现象:

  • 系统响应变慢,但未出现崩溃或 OOM
  • CPU 使用率并不高,但 iowait 明显升高
  • 内存充足,无 Swap
  • 停止部分高 CPU 负载服务后,问题仍然存在

初步判断:瓶颈不在 CPU 和内存,而可能在磁盘 I/O


二、第一步:整体负载判断(top)

通过 top 观察系统整体状态,发现:

  • %id(CPU idle)仍然较高
  • %wa(I/O wait)在 20%~40% 区间波动
  • 多个进程处于 D(不可中断 I/O)状态

这类特征通常意味着:

CPU 有空闲,但进程在等待磁盘 I/O 完成。

此时需要进入磁盘层面分析。


三、第二步:磁盘层分析(iostat)

使用:

iostat -xz 1

重点关注以下指标:

  • %util
  • await
  • r/sw/s
  • rkB/swkB/s

关键观测结果

  • %util 长时间维持在 90%~99%
  • await(读/写等待)在 10–40 ms 区间
  • 吞吐量仅为 几百 KB/s ~ 几 MB/s

这说明:

磁盘并非被“大流量读写”压满,而是被 高频小块 I/O(IOPS) 打满。

这是数据库 + 元数据密集型负载的典型特征。


四、第三步:进程级定位(iotop)

使用:

iotop -oPa

该工具可以实时展示 哪些进程在进行磁盘读写

观察到的主要 I/O 来源

  1. 关系型数据库进程
    • 同时存在持续读与写
    • 单次写入不大,但频率极高
  2. 文档型数据库进程
    • 写入量较小,但写操作对磁盘延迟敏感
  3. 应用层进程(Java / Node 等)
    • 少量、持续的小写入
    • 单个进程影响有限,但叠加后会增加队列压力
  4. Web 层进程(PHP-FPM)
    • 自身 I/O 很低
    • 主要作用是触发数据库操作

系统级进程(日志、容器运行时等)均处于正常噪音水平。


五、负载模式分析

综合 topiostatiotop 的结果,可以得到完整因果链:

应用请求
   ↓
数据库查询 / 事务
   ↓
频繁小块同步写(redo / journal)
   ↓
文件系统日志层
   ↓
物理磁盘 I/O 队列打满
   ↓
CPU iowait 上升

这是一个教科书级的磁盘 I/O 瓶颈案例


六、可能的直接诱因:文件同步行为

进一步结合业务场景,发现一个高度相关的可能性:

用户正在进行文件同步操作(如私有云客户端同步)

这类同步具有以下特征:

  • 大量小文件
  • 高频元数据更新
  • 数据库表(如 file cache、activity、lock 表)被频繁写入
  • 吞吐量不高,但 IOPS 与 fsync 压力极大

其表现形式与当前监控数据完全一致。


七、是否属于异常状态?

结论是:不是异常,而是硬件能力边界的体现

  • 系统不会立即崩溃
  • 不会触发 OOM
  • 不会造成数据损坏

但在该状态下:

  • 响应延迟会上升
  • 不适合继续增加写密集型服务
  • 不适合进行批量扫描、索引或维护操作

八、可行的应对策略(不升级硬件前提下)

短期(止血)

  • 等待同步类任务自然结束
  • 避免并发执行数据库维护任务
  • 控制日志级别,避免 debug 写盘

中期(缓解)

  • 减少数据库不必要的同步写
  • 合理规划文件同步行为(避免频繁全量扫描)

长期(根治)

  • 升级磁盘性能(SSD / NVMe)

在该案例中,磁盘是唯一明确的性能天花板


九、总结

这次排查的关键价值不在于“发现问题”,而在于:

  • 没有凭感觉下结论
  • 按层次逐步缩小范围
  • 使用了正确的工具
  • 得到了可验证、可复现的判断

top → iostat → iotop 的组合,是排查 Linux I/O 性能问题的稳定路径。

当 CPU 与内存看似充足,却出现系统“卡顿”时,磁盘 I/O 往往才是真正的瓶颈。


(全文已脱敏,侧重工程分析方法,不涉及具体业务细节)

Leave a Reply

Your email address will not be published. Required fields are marked *