Linux 在操作文件时,将数据放入文件缓存区,直到内存不够或系统要释放内存给用户进程使用,因此在查看 Linux 内存状况时经常会发现可用的物理内存不多,但 cached 用了很多,这是Linux提升文件IO速度的一种做法。

这种情况下,如物理空闲内存够用,通常在Linux上只有写文件和第一次读取文件时会产生真正的文件IO

在 Linux 中,主要通过 pidstat 来查找文件 IO 的消耗

pidstat

pidstat –d –t –p[pid] 1 100 查看线程的 IO 消耗状况,要在 2.6.20 以上版本有效。
image.png

参数 含义
TID 表示线程 ID
KB_rd/s 表示每秒读取的 KB 数
KB_wr/s 表示每秒写入的 KB 数

iostat

在没有 pidstat 的情况下,只能通过 IOSTAT 来查看整个系统的文件 IO 消耗状况,无法跟踪进程的文件 IO 消耗状况。

直接输入 iostat,可查看各个设备的IO历史情况
image.png

参数 含义
tps 是每秒的 IO 请求数
Blk_read/s 是指每秒读的块数量,通常块的大小为 512 字节
blk_write 指每秒写的块数量
blk_read/blk_wrtn 指总共读/写的块数量

还可以通过

iostat –x xvda 3 5

输出信息会相对多一些,

参数 含义
r/s 表示每秒读请求数
w/s 指每秒写请求数
await 表示平均每次 IO 操作的等待时间 (ms)
avgqu-sz 表示等待请求的队列的平均长度
svctm 表示平均每次设备执行 IO 操作的时间
util 表示一秒之中有百分之几用于 IO 操作。

使用 iostat 时,首要关注 CPU 中的 iowait% 所占的百分比,当 iowait 占了主要的百分比时,就要关注 IO 方面的消耗状况了。

JAVA 应用造成文件 IO 消耗严重主要是:

  • 多个线程需要进行大量内容写入 ( 如频繁的日志写入 ) 的动作
  • 或磁盘设备本身处理速度慢
  • 或文件系统慢
  • 或操作的文件本身已经很大造成。

总结

  • 如果IO过高,表明应用程序在频繁的读写硬盘文件
    • 因此可先用pidstat -d -t -p pid 或iostat查找在io的线程,并结合jstack找到对应线程执行的java代码。
    • 解决方法:缓冲区,异步写文件,批量读写,限制写单个文件的最大文件大小