当你发现生产环境某些IO进程读写效率下降,可以考虑Linux系统是否存在IO性能瓶颈了,而以下便是笔者整理的一套比较普适的IO性能瓶颈通用排查方法论。
当你发现生产环境某些IO进程读写效率下降,例如:
- MySQL查询耗时增高
- 文件读写效率变慢

此时我们就可以考虑Linux系统是否存在IO性能瓶颈了,而以下便是笔者整理的一套比较普适的IO性能瓶颈通用排查方法论,同时为了更好地复现这个问题,笔者也用Java写了一个多线程执行数据读写的程序,读者可以查看如下代码结合注释了解一下这个逻辑:
/**
* 启动磁盘I/O操作以模拟高I/O负载
* 通过创建多个I/O任务线程来模拟高磁盘I/O负载
*/
private static void startDiskIOOperations() {
log.info("开始高I/O磁盘操作...");
log.info("在另一个终端中运行 'iostat -x 1' 来监控磁盘利用率。");
// 创建固定线程数的线程池
executor = Executors.newFixedThreadPool(NUM_THREADS);
// 提交多个任务以连续写入磁盘
for (int i = 0; i < NUM_THREADS; i++) {
executor.submit(new IOTask(i));
}
log.info("磁盘I/O操作已启动,使用 {} 个线程", NUM_THREADS);
}
/**
* 执行连续写入操作以模拟高I/O的任务
* 该类负责执行磁盘I/O操作,通过不断写入和清空文件来模拟高I/O负载
*/
static class IOTask implements Runnable {
private final int taskId;
public IOTask(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
// 每个线程写入自己的临时文件
String filename = "/tmp/disk_io_test_" + taskId + ".tmp";
try (FileOutputStream fos = new FileOutputStream(filename)) {
log.info("线程-{} 正在写入 {}", taskId, filename);
// 连续将数据写入文件并在每次写入后清空文件
while (!Thread.currentThread().isInterrupted()) {
performDiskIOOperation(fos, taskId);
ThreadUtil.sleep(500);
}
} catch (IOException e) {
log.error("线程-{} 发生错误: {}", taskId, e.getMessage());
}
}
}
/**
* 执行磁盘I/O操作:写入指定大小的数据然后清空文件
* 该方法会连续写入数据到文件,然后清空文件内容,用于模拟高I/O负载
* @param fos 文件输出流
* @param taskId 任务ID
* @throws IOException IO异常
*/
private static void performDiskIOOperation(FileOutputStream fos, int taskId) throws IOException {
long startTime = System.currentTimeMillis();
// 写入数据(分块写入)
long bytesWritten = 0;
while (bytesWritten < WRITE_SIZE) {
fos.write(DATA);
bytesWritten += DATA.length;
}
fos.flush(); // 强制写入磁盘
// 清空文件内容
fos.getChannel().truncate(0);
long endTime = System.currentTimeMillis();
// 打印本次操作的耗时
log.info("线程-{} 完成一次写入和清空操作,耗时: {} ms", taskId, (endTime - startTime));
}
详解Linux系统IO性能问题排查通用方法论
1. 检查服务器负载
当我们认为存在IO瓶颈时,首先要做的就是基于top指令查看当前服务器wa即CPU等待IO任务完成的占比,一般情况下20%以下算是一个比较合理的正常阈值,超过30%-40%则表明系统可能存在严重的IO瓶颈。以笔者的服务器为例,可以看到wa的值远大于正常范围,说明当前CPU基本处于等待IO任务完成的情况:
Tasks: 34 total, 1 running, 33 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.5 us, 2.6 sy, 0.0 ni, 5.3 id, 90.5 wa, 0.0 hi, 1.1 si, 0.0 st
%Cpu1 : 0.0 us, 2.2 sy, 0.0 ni, 24.9 id, 72.4 wa, 0.0 hi, 0.5 si, 0.0 st
%Cpu2 : 1.1 us, 0.6 sy, 0.0 ni, 0.6 id, 97.7 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.5 us, 2.7 sy, 0.0 ni, 16.8 id, 80.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu4 : 0.6 us, 1.7 sy, 0.0 ni, 0.0 id, 97.8 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu5 : 0.0 us, 3.9 sy, 0.0 ni, 18.8 id, 77.3 wa, 0.0 hi, 0.0 si, 0.0 st
2. 查看IO使用率
明确系统存在IO性能瓶颈的情况下,我们就需要更进一步定位问题,以笔者为例,一般会执行iostat指令,如下所示,大意为:
- -x:显示更多扩展信息(包括设备利用率、等待时间等)
- 每1秒输出1次,持续输出
iostat -x 1
从输出结果来看,对应sdd盘使用率%util(IO利用率)飙到100%且iowait达到了78.2%,很明显这块磁盘存在一些异常IO读写任务:
avg-cpu: %user %nice %system %iowait %steal %idle
0.0% 0.0% 1.0% 78.2% 0.0% 20.8%
Device r/s rMB/s rrqm/s %rrqm r_await rareq-sz w/s wMB/s wrqm/s %wrqm w_await wareq-sz d/s dMB/s drqm/s %drqm d_await dareq-sz f_await aqu-sz %util
sda 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 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdb 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 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc 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 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdd 4.00 0.04 0.00 0.00 122.25 10.24 171.00 190.81 1.00 0.58 3884.17 1.12 0.00 0.00 0.00 0.00 0.00 0.00 0.00 664.68 100.00
关键指标解读:
- %util:设备利用率,接近100%表示设备繁忙,可能存在IO瓶颈
- r_await 和 w_await:平均读写请求等待时间,数值越高说明IO响应越慢
- aqu-sz:平均请求队列大小,数值较大说明IO请求堆积严重
- await:平均服务时间(读写等待时间之和)
3. 明确定位IO进程
基于上述过程我们已经明确sdd盘存在IO异常,此时我们就可以通过iotop来查看具体进程了,需要补充的是iotop默认是没有安装的,读者可以参考网上教程自行安装,以笔者的Ubuntu系统为例,对应的安装指令为:
sudo apt install iotop
最后键入sudo iotop -o查看正在执行IO操作的进程,此时就可以非常明确地看到笔者Java进程对应执行异常IO操作的线程和读写速率了:
Total DISK READ: 0.00 B/s | Total DISK WRITE: 142.99 M/s
Current DISK READ: 11.92 K/s | Current DISK WRITE: 336.21 M/s
TID PRIO USER DISK READ DISK WRITE> COMMAND
3253712 be/4 sharkchi 0.00 B/s 18.26 M/s java -jar web-cache-1.0.jar --app.startup.method=1 [pool-2-thread-3]
3253713 be/4 sharkchi 0.00 B/s 18.26 M/s java -jar web-cache-1.0.jar --app.startup.method=1 [pool-2-thread-4]
3253711 be/4 sharkchi 0.00 B/s 18.25 M/s java -jar web-cache-1.0.jar --app.startup.method=1 [pool-2-thread-2]
3253715 be/4 sharkchi 0.00 B/s 18.25 M/s java -jar web-cache-1.0.jar --app.startup.method=1 [pool-2-thread-6]
3253714 be/4 sharkchi 0.00 B/s 18.24 M/s java -jar web-cache-1.0.jar --app.startup.method=1 [pool-2-thread-5]
3253710 be/4 sharkchi 0.00 B/s 17.50 M/s java -jar web-cache-1.0.jar --app.startup.method=1 [pool-2-thread-1]
3253717 be/4 sharkchi 0.00 B/s 17.50 M/s java -jar web-cache-1.0.jar --app.startup.method=1 [pool-2-thread-8]
3253716 be/4 sharkchi 0.00 B/s 16.74 M/s java -jar web-cache-1.0.jar --app.startup.method=1 [pool-2-thread-7]
4. 补充:其他有用的IO分析工具
在实际排查中,除了上述工具外,还有其他一些有用的工具可以辅助分析:
- pidstat -d 1:显示每个进程的IO统计信息
- iotop -a:按IO累计使用量排序
- vmstat 1:显示虚拟内存统计,包括IO相关指标
- lsof +D /path/to/directory:列出打开指定目录下文件的进程
小结
我们来简单小结一下IO性能瓶颈的排查套路:
- 通过top命令查看%wa(iowait)指标,判断CPU是否存在异常等待IO的情况
- 使用iostat -x 1查看IO使用率和响应时间等详细指标,定位具体磁盘设备
- 使用iotop显示正在执行IO任务的进程和线程,明确问题程序
- 结合其他工具如pidstat、vmstat等进行深入分析
AI大模型学习福利
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
一、全套AGI大模型学习路线
AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
四、AI大模型商业化落地方案

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量
1246

被折叠的 条评论
为什么被折叠?



