禅与计算机 禅与计算机
首页
  • Java基础

    • 一文搞懂Java核心技术
    • Java面向对象知识点大总结,建议收藏
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
    • Java异常:从原理到实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
    • 探索JVM的隐秘角落:元空间详解
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 元认知

    • 摩擦感:AI时代的写作自省
    • 从断墨寻径浅谈程序员的元学习能力
    • AI时代专注力培养
    • 如何阅读一本书:技术书籍的读书笔记方法论
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • Elasticsearch核心原理与架构设计
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
  • AI工具链

    • Claude Code 实战指南:从安装配置到企业级开发流程
    • 一次 Claude Code 启动失败的 AI 辅助排查复盘
    • Claude Code 记忆管理:CLAUDE.md 最佳实践
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

sharkchili

计算机禅修者
首页
  • Java基础

    • 一文搞懂Java核心技术
    • Java面向对象知识点大总结,建议收藏
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
    • Java异常:从原理到实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
    • 探索JVM的隐秘角落:元空间详解
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 元认知

    • 摩擦感:AI时代的写作自省
    • 从断墨寻径浅谈程序员的元学习能力
    • AI时代专注力培养
    • 如何阅读一本书:技术书籍的读书笔记方法论
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • Elasticsearch核心原理与架构设计
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
  • AI工具链

    • Claude Code 实战指南:从安装配置到企业级开发流程
    • 一次 Claude Code 启动失败的 AI 辅助排查复盘
    • Claude Code 记忆管理:CLAUDE.md 最佳实践
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 计算机组成原理

  • 操作系统

  • 计算机网络

  • 运维

    • Linux性能问题排查最佳实践
    • Linux上IO性能问题的故障排除实践
      • 引言
      • 背景说明
      • 详解Linux系统IO性能问题排查通用步骤
        • 检查服务器负载
        • 查看IO使用率
        • 明确定位IO进程
      • 小结
      • 参考
  • 编码最佳实践

  • 计算机基础
  • 运维
sharkchili
2025-12-12
目录

Linux上IO性能问题的故障排除实践

# 引言

在诸如grafana、Nightingale等监控工具盛行的今天,软件开发工程师仍然需要具备面向操作系统维度的性能指标以及终端排查的思想沉淀,确保在日常工程开发和极端环境下都具备足够力道的系统调优能力。而本文将从一个经典的并发IO读写性能引发的用户应用延迟升高的故障深入演示一下传统性能瓶颈分析和排查的手段,希望对你有所启发。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:https://github.com/shark-ctrl/mini-redis (opens new window)。

为方便与读者交流,现已创建读者群。关注下方公众号获取我的联系方式,添加时备注加群即可加入。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:https://github.com/shark-ctrl/mini-redis。

为方便与读者交流,现已创建读者群。关注上方公众号获取我的联系方式,添加时备注加群即可加入。

# 背景说明

为了更好地复现本次故障,笔者也用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);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

与之对应IOTask的逻辑也非常简单频繁大批量读写文件,完成后再清空,模拟并发场景下频繁的大文件读写操作:

/**
 * 执行连续写入操作以模拟高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));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 详解Linux系统IO性能问题排查通用步骤

# 检查服务器负载

当我们认为存在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
1
2
3
4
5
6
7

# 查看IO使用率

明确系统存在IO性能瓶颈的情况下,我们就需要更进一步定位问题,以笔者为例,一般会执行iostat指令,如下所示,大意为:

  1. -x:显示更多扩展信息(包括设备利用率、等待时间等)
  2. 每1秒输出1次,持续输出
iostat -x 1
1

输出结果如下,对应的比这也针对这些指标的阈值进行一些简单的说明:

关键指标解读:

  • %util:设备利用率,接近100%表示设备繁忙,可能存在IO瓶颈
  • r_await 和 w_await:平均读写请求等待时间,数值越高说明IO响应越慢
  • aqu-sz:平均请求队列大小,数值较大说明IO请求堆积严重
  • await:平均服务时间(读写等待时间之和)
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
1
2
3
4
5
6
7
8

结合我们实际监控到的指标来看,对应sdd盘使用率%util(IO利用率)飙到100%且iowait达到了78.2%,很明显这块磁盘存在一些异常IO读写任务:

# 明确定位IO进程

基于上述过程我们已经明确sdd盘存在IO异常,此时我们就可以通过iotop来查看具体进程了,需要补充的是iotop默认是没有安装的,读者可以参考网上教程自行安装,以笔者的Ubuntu系统为例,对应的安装指令为:

sudo apt install iotop
1

最后键入sudo iotop -o查看正在执行IO操作的进程,对应输出结果如下,对应字段含义分别是:

  • Total DISK READ: 总磁盘读
  • Total DISK WRITE: 总磁盘写
  • Current DISK READ: 瞬时磁盘读
  • Current DISK WRITE: 瞬时磁盘写
  • TID:线程号
  • PRIO:io进程优先级
  • USER:进程所属用户
  • DISK READ :该线程读取速率
  • DISK WRITE:该线程写入速率
  • COMMAND:执行线程的命令(对应java进程启动指令)

此时就可以非常明确地看到笔者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]
1
2
3
4
5
6
7
8
9
10
11

# 小结

我们来简单小结一下IO性能瓶颈的排查套路:

  1. 通过top命令查看%wa(iowait)指标,判断CPU是否存在异常等待IO的情况
  2. 使用iostat -x 1查看IO使用率和响应时间等详细指标,定位具体磁盘设备
  3. 使用iotop显示正在执行IO任务的进程和线程,明确问题程序

简而言之无论是面向shell终端的性能排查还是基于时序库采集到的监控图表,我们从性能优化方法论的角度出发,整体步骤也都是严格遵循:

  1. 结合问题表象推测故障性质,是CPU活跃性问题还是IO性质的瓶颈
  2. 结合推断查看指定指标,例如CPU利用率或者网络带宽、磁盘利用率、io等待时长等
  3. 明确问题根因后,定位目标进程
  4. 结合程序类型采用相应故障诊断工具定位问题代码段

当然,对于有足够经验的工程师而言,可能大部分都会在top指令完成后,明确存在io性能瓶颈且当前服务器是java进程专用后,就会直接通过iotop定位问题了,而这就是所谓的经验。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:https://github.com/shark-ctrl/mini-redis (opens new window)。

为方便与读者交流,现已创建读者群。关注下方公众号获取我的联系方式,添加时备注加群即可加入。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:https://github.com/shark-ctrl/mini-redis。

为方便与读者交流,现已创建读者群。关注上方公众号获取我的联系方式,添加时备注加群即可加入。

# 参考

【双语视界】Linux上IO性能问题的故障排除:https://www.bilibili.com/video/BV14d35zhEjs/?from_spmid=united.player-video-detail.drama-float.0&plat_id=411&share_from=season&share_medium=iphone&share_plat=ios&share_session_id=2A52FF3A-393E-4D48-98A0-712F961E6C3A&share_source=WEIXIN&share_tag=s_i&spmid=united.player-video-detail.0.0&timestamp=1758040810&unique_k=gAzBCJY&vd_source=bf04f9a485aa892c0242fbfdfca25589 (opens new window)

编辑 (opens new window)
上次更新: 2026/02/03, 09:15:24
Linux性能问题排查最佳实践
浅谈现代软件工程TDD最佳实践

← Linux性能问题排查最佳实践 浅谈现代软件工程TDD最佳实践→

最近更新
01
Claude Code 记忆管理:CLAUDE.md 最佳实践
04-24
02
Claude Code 实战指南:从安装配置到企业级开发流程
04-20
03
一次 Claude Code 启动失败的 AI 辅助排查复盘
04-18
更多文章>
Theme by Vdoing | Copyright © 2025-2026 Evan Xu | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×
×