剑指“磁盘IO高busy”问题

3,330 阅读5分钟

「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

一、什么是磁盘IO高busy

  磁盘io高busy一般会发生在一些写入写出极其频繁的应用服务器上。
  比如安装了数据库的服务器,常见于mysql、oracle等服务器在高并发环境下很容易出现io高busy,究其原因,产生磁盘io高busy的原因一般都是有大量写操作导致。
  比如就拿oracle来说,因为oracle除了正常的数据写入写出外,还有redo和undo操作,即事物日志,用来做回滚和提交。这两个在大量的update或者insert操作中是很容易导致io高busy的。
  一般我们认为io的busy达到80%以上就该预警了。
  在高并发下这种问题是很常见的。我们通过压力测试工具可以很容易模拟出来。

image.png

如上图所示:红色框选出来的磁盘io已经达到85%(nmon工具)。

二、为什么会磁盘IO高busy

  磁盘高频率写入写出,存储分散,磁盘指针来回跳,这些都会导致磁盘io高busy。
  大量的小文件就会增加磁盘的磁头寻找扫描时间。
  “怎样高效的处理io”其实是一个比较大的话题,优秀的数据处理框架,针对这一块都做了很多的优化处理。

三、躺平式处理磁盘IO高busy

  磁盘io高busy一般会出现在数据库服务器和文件处理服务器上。
  我们处理的比较多的其实是数据库服务器的磁盘io高busy。

1、通过linux命令找到大量的写线程命令

 有多种工具可以看到linux中磁盘 IO 负载。
 iostat 从系统维度查看 IO 负载情况。
 iotop 从进程纬度查看磁盘 IO 负载
 iostat和iotop 并非常见 Linux 发行版本自带工具,其包含在 sysstat 软件包中,需要先通过 yum 或 apt-get 等方式进行安装后才能使用。

命令参考:
 iostat -x 1 12  查看磁盘io情况
 iotop -oP  查看进程操作io
 pidstat -d 1  进行I/O统计,每秒更新一次
 iotop -p $PID -d 1  单个进程进行查看该进程io情况
 其实通过 iotop 命令看到进程的信息就相当于看到线程io情况了,具体图片由于当时作者没有截取,这是后来补的。

2、排查出该线程是在做什么操作

  jstack命令可以查看堆栈信息,即可以查看线程在干什么。其实第一步那里大多数情况下就可以看到是什么原因导致的io高busy了。

3、排查出为什么会做该操作

  排查出是因为什么导致的磁盘高busy后,其实就可以考虑进行优化了。

4、针对3的结果进行优化

  优化的方案有很多,如果是磁盘问题,可以考虑换磁盘。如果是因为代码原因或者业务逻辑原因,这时候就要进行调整了。

5、考虑优化方案

代码上优化

  代码上优化是比较简单的优化,基本是由于一些错误代码导致,这种一般在测试时就会被筛出来。

技术方案上优化

  技术上优化需要考虑用其他技术来替代。比如spring session 有多种方案,有redis、jdbc、hashmap…等等,如果使用jdbc就相当于每一次后端操作(包括查询),都会对数据库造成写操作,如果是在oracle数据库,这就相当于会产生大量的undo和redo信息了,这样其实如果有大量访问操作的话其实很容易发生io高busy。所以通过这一点也可以看出程序开发完成后的优化这一步是多么的重要,也可以看出不同技术选型,不同场景下对性能的重要性。

业务方向优化

  业务优化上来说,就比较复杂了,这需要擅长这个领域才可以。

四、一个栗子

栗子概要:高并发下oracle服务器上的磁盘io高busy。

image.png

环境:
  oracle19
  weblogic12c
   ……
  以前,有一次生产上io警报响起,排查日志发现只有大量访问请求,可就是这些访问请求竟然导致数据库的磁盘io使用率达到了80%以上。这是什么鬼情况?很果断的,我导出了oracle数据库这个时间段的awr报告,发现里面竟然有很多update操作,这是什么鬼?通过排查sql发现是spring session的jdbc配置导致,而后进行了优化,使用redis做了session的存储操作。 这个小栗子说明磁盘高busy是很容易排查的(并不是以偏概全,作者也处理过许多io高busy的问题,或性能测试时,或生产上,总的来说,其实处理起这类问题还是相对容易的),确定好思路,笃定方案,一步一操作,很快就排查出来了。考虑的场景也要不仅局限于数据库这台服务器,还要考虑整体的web服务等和具体代码实现。