Ubuntu 22.04 系统中不明原因的磁盘 I/O 高负载:如何利用 iotop 和 systemd 排查优化

当数据中心的一台 Ubuntu 22.04 香港服务器www.a5idc.com出现 磁盘 I/O 持续高负载 时,很容易影响业务性能(如 MySQL 延迟、NFS 挂载卡顿、容器写盘阻塞等)。本文结合我在跨境电商平台运维中的实际案例,讲述如何使用 iotopsystemd 工具链 等定位根因,并给出优化方案与评估数据。


一、问题背景与现象描述

凌晨,A5数据的监控系统告警:

  • iowait CPU 时间持续在 30% 以上
  • 关键业务响应时间突然变长
  • SSD 磁盘队列深度异常增长

在排查指标时,我们注意到:

指标名称 当前值 正常阈值
iowait % ~32% < 5%
avgqu-sz ~15 < 5
await (ms) ~40 < 20
svctm (ms) ~8 < 5

这些指标均由 iostat -x 5 输出采集。


二、现场服务器硬件与环境参数

在分析前,我们先列出受影响香港服务器的硬件配置,以便后续定位:

项目 规格/型号
机型 Dell PowerEdge R650
CPU Intel Xeon Silver 4310 (12核心/24线程)
内存 128GB DDR4 ECC
操作系统 Ubuntu 22.04.4 LTS (内核 5.15)
磁盘 2× NVMe SSD (Samsung PM9A3 3.84TB, RAID1)
文件系统 XFS
关键服务 MySQL 8.0, Docker 容器, systemd 管理

三、诊断工具与思路

我们主要依赖以下工具:

工具 作用
iotop 监控实时 I/O 行为
systemd-cgtop 查看 cgroup(服务/容器)I/O 使用
systemd-analyze blame 评估启动阶段耗时(与 I/O 相关服务)
iostat 长周期统计磁盘性能指标
strace 跟踪进程系统调用(非必选,用于深度定位)

四、步骤详解:如何使用 iotop 定位 I/O 顶流进程

1)安装与运行 iotop

bash 复制代码
sudo apt update
sudo apt install -y iotop

运行:

bash 复制代码
sudo iotop -o -b -t 5 > /tmp/iotop.log &

参数说明:

  • -o:仅显示正在进行 I/O 的进程
  • -b:批处理模式(适合日志分析)
  • -t:时间戳输出

输出类似:

复制代码
2025-01-02 09:15:10
TID    PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
12345  be/4  mysql    0.00 B/s    30.2 M/s   0.00 %   15.20 % mysqld
23456  be/4  root     0.00 B/s    8.4 M/s    0.00 %    4.10 % docker-containerd
...

五、结合 systemd 工具链判断服务级别 I/O 压力

1)使用 systemd-cgtop 观察单位服务行为

bash 复制代码
sudo systemd-cgtop -b -n 5

输出主要关注 IO% 列:

复制代码
CGROUP                           TASKS   %CPU   %MEM   IO
/                               112      9.1    35.2   18.3
/system.slice/mysqld.service     28      3.8    12.7   13.9
/system.slice/docker.service     45      2.6    10.1    4.2
...

从这个输出,我们可以明确定位到 mysqld.service 对磁盘 I/O 贡献最大。

2)分析 systemd 启动阶段 I/O 延迟

虽然不是故障根因,但了解启动 I/O 冲突也有帮助:

bash 复制代码
systemd-analyze blame | head -n 10

若某个服务启动耗时过长,也可能反映 I/O 相关瓶颈。


六、真实案例分析:mysqld 磁盘写放大

通过 iotopsystemd-cgtop 我们确认 mysqld 是 I/O 主因,但进一步观察发现:

  • 写入主要集中在 binlogInnoDB redo log
  • 磁盘延迟(await)波动明显

1)Redistribute 写负载

我们在 MySQL 中启用了 Group Commitinnodb_flush_log_at_trx_commit=2(牺牲一部分持久性换取性能):

sql 复制代码
SET GLOBAL innodb_flush_log_at_trx_commit=2;
SET GLOBAL sync_binlog=100;

这样可以减少每次事务提交对磁盘的强制刷写,提高整体吞吐。


七、优化方案与执行

方案一:调整 IO 调度器

Ubuntu 22.04 默认使用 mq-deadline。对 NVMe SSD 可尝试 none 以减少 CPU 调度开销:

bash 复制代码
for d in /sys/block/nvme*; do
  echo none | sudo tee $d/queue/scheduler
done

持久化:

bash 复制代码
cat <<EOF | sudo tee /etc/udev/rules.d/60-ioschedulers.rules
ACTION=="add|change", KERNEL=="nvme*", ATTR{queue/scheduler}="none"
EOF

方案二:限制容器 I/O

如果 Docker 容器占用严重,可设置 cgroup 限制:

bash 复制代码
docker run -d \
  --name webapp \
  --device-write-bps /dev/nvme0n1:50mb \
  --device-read-bps /dev/nvme0n1:50mb \
  your-image

方案三:升级硬件队列深度

bash 复制代码
sudo nvme get-feature /dev/nvme0n1 -f 7 -H

若队列深度小于 1024,可视负载提升队列设置。


八、优化前后评估数据

以下为调整前后部分关键指标对比:

指标 优化前 优化后
avgqu-sz 14.8 4.2
iowait % 31.7 8.5
await (ms) 39.6 19.3
mysqld IO% ~13.9 ~7.1
容器总体 I/O ~22.5% ~10.4%

九、注意事项与最佳实践

  • 监控告警要覆盖 I/O 延迟:例如 await > 20ms 时触发。
  • 生产环境调参需逐步验证:每次调整后至少观察 30 分钟以上。
  • 避免与备份窗口重叠:定时备份造成瞬时 I/O 峰值。

十、结语

通过 iotopsystemd 工具链,我们能快速定位磁盘 I/O 高负载的罪魁祸首,并从服务层、调度器层到容器层多角度优化。在 Ubuntu 22.04 的服务器上,这样的组合是故障排查的利器。希望本文的步骤、表格和实战建议,能帮助你在类似的运维场景中快速解决问题。

相关推荐
testpassportcn2 小时前
微軟 DP-600 認證介紹|Microsoft Fabric Analytics Engineer Associate 完整解析與考試攻略
运维·fabric
释怀不想释怀2 小时前
打包部署(vue前端)(Nginx)
运维·nginx
fengyehongWorld2 小时前
Linux systemd 与 systemctl 命令
linux·运维·服务器
公众号:ITIL之家2 小时前
服务价值体系重构:在变化中寻找不变的运维本质
java·运维·开发语言·数据库·重构
Howrun7772 小时前
不可重入函数Non-Reentrant & 可重入函数Reentrant
linux·服务器
0思必得02 小时前
[Web自动化] Requests模块请求参数
运维·前端·python·自动化·html
oMcLin2 小时前
Debian 9 高并发请求导致 Nginx 进程崩溃:调整 worker_processes 和 worker_connections 参数
运维·nginx·debian
Thera7772 小时前
Linux 核心绑定(CPU Affinity)详解:原理、方法与优缺点分析
linux·运维·服务器
不一样的故事1262 小时前
1. 公司质量体系的维护与申办监管•
大数据·运维·人工智能