目录

4.11 磁盘监测命令

本节我们来介绍磁盘相关的监测工具。

1. 命令总览

下面的图片摘录自极客时间专栏-Linux性能优化实战,分别从下面 3 个方面总结了磁盘相关的性能检测工具:

  1. 从磁盘的性能指标出发,根据指标找工具
  2. 从工具出发,根据工具找指标
  3. 根据工具指标之间的内在联系,掌握磁盘分析的套路

/images/linux_pf/disk_quota.png /images/linux_pf/disk_command.png /images/linux_pf/disk_relation.png

有些工具是通用的分析工具,后面会在单独的章节中详细说明他们的使用。本节会介绍如下磁盘专用的分析工具的使用

Linux Solaris 作用 说明
iostat iostat 各种单个磁盘的统计信息
pidstat,iotop iotop 按进程列出磁盘I/O使用情况
blktrace iosnoop 磁盘I/O事件追踪
MegaCli MegaCli LSI控制统计信息
smartctl smartctl 磁盘控制器统计信息
sar sar 磁盘历史统计信息 通用命令,位于独立的一节中
lsof lsof 查看进程打开的文件列表
biosnoop biosnoop 跟踪进程的块设备I/O大小 bcc工具包
biotop biotop 跟踪进程块I/O大小并实时排序 bcc工具包

除此之外,还包括以下内容:

  1. 磁盘性能测试
  2. 磁盘性能调优

2. 磁盘统计命令

2.1 iostat

iostat options [interval [count]]

  • 作用: 单个磁盘的统计信息,统计信息的来源直接由内核维护,几乎没有开销
  • 默认: 打印自启动以来的 -c和-d 选项的汇总报告
  • 说明: SCSI 设备包括磁带和 CD-ROM 在当前Linux 不会显示
  • 来源: iostat 的数据来自 /proc/diskstats
  • 参数:
    • -c: 显示 CPU 报告
    • -d: 显示磁盘报告
    • -k: 使用 KB代替(512B)块数量
    • -m: 使用 MB代替(512B)块数量
    • -p: 包括单个分区的统计信息
    • -t: 时间戳输出
    • -x: 扩展统计信息
    • -z: 不显示空活动汇总
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 iostat 
Linux 3.10.0-1062.el7.x86_64 (hostname)    2020年04月21日  _x86_64_        (1 CPU)

# 启动以来的CPU和磁盘设备统计信息
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.39    0.00    0.22    0.01    0.00   99.37

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               1.71        67.68         5.39     925064      73658
dm-0              1.64        65.32         5.24     892891      71574
dm-1              0.01         0.16         0.00       2204          0

输出:

  1. tps: IOPS 每秒事务数
  2. kB_read/s: 每秒读KB数
  3. kB_wrtn/s: 每秒写KB数
  4. kB_read: 总读取KB数
  5. kB_wrtn: 总写入KB数

扩展输出

1
2
3
4
5
6
7
iostat -xkdz 1
Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain)    2020年04月21日  _x86_64_        (1 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.07    1.37    0.29    65.70     5.25    85.36     0.00    1.38    0.69    4.60   0.48   0.08
dm-0              0.00     0.00    1.28    0.32    63.41     5.10    85.88     0.00    1.67    0.72    5.46   0.49   0.08
dm-1              0.00     0.00    0.01    0.00     0.16     0.00    50.09     0.00    0.23    0.23    0.00   0.17   0.00
输出 含义
rrqm/s 每秒合并放入驱动请求队列的读请求数
wrqm/s 每秒合并放入驱动请求队列的写请求数
r/s 每秒发给磁盘设备的读请求书,这是实际发给磁盘的请求数
w/s 每秒发给磁盘设备的写请求书,这是实际发给磁盘的请求数
rkB/s 每秒从磁盘设备读取的 KB 数
wkB/s 每秒向磁盘设备写入的 KB 数
avgrq-sz 平均请求大小,单位为扇区(512B)
avgqu-sz 在驱动请求队列和在设备中活跃的平均请求数
await 平均I/O响应时间,包括在驱动请求队列里等待和设备的I/O响应时间(ms)
r_await 同awit,不过只针对读
w_await 同awit,不过只针对写
svctm 推断的磁盘设备的I/O平均响应时间
%util 使用率,设备忙处理I/O请求的百分比

说明:

  1. 非零的 rrqm/s 和 wrqm/s 说明为了提高性能,连续的请求在发往设备之前已经被合并了,这个指标也是工作负载为连续的标志
  2. avgrq-sz 是合并之后的数字,小尺寸(16个扇区或者更小)可以视为无法合并的随机I/O负载。大尺寸有可能是大I/O,或者是合并的连续负载
  3. r/s+w/s ,就是 IOPS;
  4. rkB/s+wkB/s ,就是吞吐量;
  5. r_await+w_await ,就是响应时间。

/images/linux_pf/iostat.png

2.2 iotop

iotop options

  • 作用:
  • 参数:
    • -o, –only只显示正在产生I/O的进程或线程。除了传参,可以在运行过程中按o生效
    • -P, –processes仅显示进程,默认iotop显示所有线程
    • -a, –accumulated显示累积的I/O,而不是带宽
    • -d SEC, –delay=SEC设置每次监测的间隔,默认1秒,接受非整形数据例如1.1
    • -p PID, –pid=PID指定监测的进程/线程
    • -u USER, –user=USER指定监测某个用户产生的I/O
    • -k, –kilobytes使用kB单位,而不是对人友好的单位。在非交互模式下,脚本编程有用
    • -b, –batch非交互模式,一般用来记录日志。
    • -n NUM, –iter=NUM设置监测的次数,默认无限。在非交互模式下很有用
    • -t, –time 加上时间戳,非交互非模式
    • -q, –quiet 禁止头几行,非交互模式。有三种指定方式
    • -q 只在第一次监测时显示列名
    • -qq 永远不显示列名
    • -qqq 永远不显示I/O汇总。
  • 交互按键:
    • left和right方向键:改变排序
    • r:反向排序
    • o:切换至选项–only
    • p:切换至–processes选项
    • a:切换至–accumulated选项
    • q:退出
    • i:改变线程的优先级
1
2
3
4
5
6

$ iotop
Total DISK READ :       0.00 B/s | Total DISK WRITE :       7.85 K/s 
Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s 
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND 
15055 be/3 root        0.00 B/s    7.85 K/s  0.00 %  0.00 % systemd-journald 

指标含义:

  1. SWAPIN, IO>: 表示换入和等待 I/O 的时钟百分比等。

2.3 disktop.stp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
> git clone git clone https://github.com/dengliu/systemtap
> cd systemtap
> stap -v disktop.stp
Tue Apr 21 14:59:27 2020 , Average:   5Kb/sec, Read:      27Kb, Write:      0Kb

     UID      PID     PPID                       CMD   DEVICE    T        BYTES
       0     9084     9083                     pgrep     dm-0    R        17864
       0     9081     9080                       awk     dm-0    R         2888
       0     9086     9082                       awk     dm-0    R         2888
       0     9087      801                     sleep     dm-0    R         1224
       0     9081     9080                  ksmtuned     dm-0    R          788
       0     9084     9083                  ksmtuned     dm-0    R          788
       0     9086     9082                  ksmtuned     dm-0    R          788
       0     9087      801                  ksmtuned     dm-0    R          788
       0     1067        1             rs:main Q:Reg     dm-0    W          120

2.4 iosnoop

iosnoop [-hQst] [-d device] [-i iotype] [-p PID] [-n name]

  • 原理: 通过块设备接口同时跟踪所有磁盘,并为每个磁盘I/O打印一条输出
  • 作用: 有助于跟踪和延时分析
  • 位置: https://github.com/brendangregg/perf-tools
  • 参数
    • -d device # device string (eg, “202,1)
    • -i iotype # match type (eg, ‘R’ for all reads)
    • -n name # process name to match on I/O issue
    • -p PID # PID to match on I/O issue
    • -Q # use queue insert as start time
    • -s # include start time of I/O (s)
    • -t # include completion time of I/O (s)
    • -h # this usage message
    • duration # duration seconds, and use buffers
命令选项组合 作用
iosnoop watch block I/O live (unbuffered)
iosnoop 1 trace 1 sec (buffered)
iosnoop -Q include queueing time in LATms
iosnoop -ts include start and end timestamps
iosnoop -i '*R*' trace reads
iosnoop -p 91 show I/O issued when PID 91 is on-CPU
iosnoop -Qp 91 show I/O queued by PID 91, queue time

输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
> git clone https://github.com/brendangregg/perf-tools
> cd perf-tools/bin
> ll iosnoop
lrwxrwxrwx. 1 tao tao 10 4月  21 23:03 iosnoop -> ../iosnoop
> sudo ./iosnoop
Tracing block I/O. Ctrl-C to end.
COMM         PID    TYPE DEV      BLOCK        BYTES     LATms
<idle>       0      WM   8,0      10911200     16384      1.48
<idle>       0      WM   8,0      30932994     512        1.47
<idle>       0      WM   8,0      30933056     16384      1.47

iosnoop 输出:

  • COMM: 进程名
  • PID
  • TYPE:
  • DEV:
  • BLOCK: 磁盘块地址,可以看出IO是否随机
  • BYTES: I/O 大小
  • LATms:

2.5 blktrace

blktrace 是一个 Linux 块设备I/O事件,包括

  1. 用来跟踪和缓冲数据的内核组件
  2. 供用户态工具使用的控制和报告机制

命令:

  1. blktrace: 启用内核驱动跟踪机制获取跟踪裸数据
  2. blkparse: 处理blktrace的数据并产生输出
  3. btrace: 合并调用上述两个程序,下面的程序是等价的
1
2
> blktrace -d /dev/sda -o -|blkparse -i -
> btrace /dev/sda

btrace 使用

btrace [-s] [-t] [-w N] [-n N] [-b N] [-r <dbg mnt>] [-a <trace>...] <dev>...

  • 选项:
    • -a trace: 设置活动的过滤条件
      • -a issue: 值跟踪 D活动(发出I/O)
      • -a read: 仅跟踪读
      • -a write: 仅跟踪写
      • -a sync: 跟踪同步操作

活动标识

活动标识 作用
A IO was remapped to a different device
B IO bounced
C IO completion
D IO issued to driver
F IO front merged with request on queue
G Get request
I IO inserted onto request queue
M IO back merged with request on queue
P Plug request
Q IO handled by request queue code
S Sleep request
T Unplug due to timeout
U Unplug request
X Split
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
> sudo btrace /dev/sda
  8,0    0        1     0.000000000     0  C   R 82106200 + 32 [0]
  8,2    0        2     0.000152172 11194  A   R 80007032 + 64 <- (253,0) 75810680
  8,0    0        3     0.000152439 11194  A   R 82106232 + 64 <- (8,2) 80007032
  8,0    0        4     0.000153208 11194  Q   R 82106232 + 64 [blkparse]
  8,0    0        5     0.000155426 11194  G   R 82106232 + 64 [blkparse]
  8,0    0        6     0.000155991 11194  P   N [blkparse]
  8,0    0        7     0.000157235 11194  I   R 82106232 + 64 [blkparse]
  8,0    0        8     0.000157845 11194  U   N [blkparse] 1
  8,0    0        9     0.000158495 11194  D   R 82106232 + 64 [blkparse]
  8,0    0       10     0.000561421     0  C   R 82106232 + 64 [0]
^CCPU0 (8,0):
 Reads Queued:           1,       32KiB  Writes Queued:           0,        0KiB
 Read Dispatches:        1,       32KiB  Write Dispatches:        0,        0KiB
 Reads Requeued:         0               Writes Requeued:         0
 Reads Completed:        2,       48KiB  Writes Completed:        0,        0KiB
 Read Merges:            0,        0KiB  Write Merges:            0,        0KiB
 Read depth:             1               Write depth:             0
 IO unplugs:             1               Timer unplugs:           0

输出默认情况下有 7 列:

  1. 设备主次号
  2. CPU ID
  3. 序号
  4. 活动时间
  5. 进程ID
  6. 活动标识符
  7. RWBS 描述: R-读,W-写,D-块丢弃,B-屏蔽操作,S-同步
  8. 后面的输出取决于活动,82106232 + 64 [blkparse] 表示一个位于地址 82106232,大小为 64 扇区,来源于 blkparse 进程

2.6 MegaCli

磁盘控制器(主机总线适配器)由系统外部的硬件和固件组成。操作系统分析工具,甚至是动态追踪都无法直接观察他们。某些特定的磁盘控制器有专门的分析工具,例如 LSI 的MegaClie

2.6 smartctl

磁盘有控制磁盘操作的逻辑,包括排队、缓存和错误处理。与磁盘控制器类似,操作系统不能直接看到磁盘的内部行为,这些信息通过观察 I/O请求和延时来推断。

许多现代驱动器提供了 SMART(自监控分析和报告分析)数据。

2.7 lsof

lsof options

  • 作用: 查看进程打开文件列表,文件包括了普通文件、目录、块设备、动态库、网络套接字等。
  • 参数:
    • -p: 指定进程ID
    • -a:列出打开文件存在的进程;
    • -c<进程名>:列出指定进程所打开的文件;
    • -g:列出GID号进程详情;
    • -d<文件号>:列出占用该文件号的进程;
    • +d<目录>:列出目录下被打开的文件;
    • +D<目录>:递归列出目录下被打开的文件;
    • -n<目录>:列出使用NFS的文件;
    • -i<条件>:列出符合条件的进程。(4、6、协议、:端口、 @ip )
    • -u:列出UID号进程详情;
    • -h:显示帮助信息;
    • -v:显示版本信息。
1
2
3
4
5
6
7
$ lsof -p 18940 
COMMAND   PID USER   FD   TYPE DEVICE  SIZE/OFF    NODE NAME 
python  18940 root  cwd    DIR   0,50      4096 1549389 / 
python  18940 root  rtd    DIR   0,50      4096 1549389 / 
python  18940 root    2u   CHR  136,0       0t0       3 /dev/pts/0 
python  18940 root    3w   REG    8,1 117944320     303 /tmp/logtest.txt 

指标含义:

  1. FD: 表示文件描述符号
  2. TYPE: 表示文件类型
  3. NAME: 表示文件路径
  4. DEVICE: 主次设备号

3. I/O 性能测试

在基准测试时,一定要注意根据应用程序 I/O 的特点,来具体评估指标。这就需要你测试出,不同 I/O 大小(一般是 512B 至 1MB 中间的若干值)分别在随机读、顺序读、随机写、顺序写等各种场景下的性能情况。

3.1 hdparm

4.磁盘调优

4.1 操作系统

ionice

ionice -c 3 -p 1623

  • 作用: 设置一个进程的 I/O 调度级别和优先级
  • 级别:
    • 0: 无,不指定优先级,内核会挑选一个默认值-尽力
    • 1: 实时,对磁盘的最高级别访问,如果误用会导致其他进程饿死
    • 2: 尽力,默认调度级别,包括优先级 0-7,0 为最高级
    • 3: 空闲,在一段磁盘空闲的期间过后才允许进行 I/O
  • 参数:
    • -c: 指定级别
    • -p: 指定进程

可调参数

  1. /sys/block/sda/queue/scheduler
    • 作用: 选择I/O调度策略
  2. /sys/block/sdb/queue/read_ahead_kb
    • 作用: 调整 /dev/sdb 磁盘预读的大小
    • 默认大小是 128 KB,单位为 KB
  3. /sys/block/sdb/queue/nr_requests
    • 作用: 调整内核磁盘队列的长度
    • 适当增大队列长度,可以提升磁盘的吞吐量(当然也会导致 I/O 延迟增大)。

磁盘故障检测

可以通过 dmesg 查看是否有硬件 I/O 故障的日志。 还可以使用 badblocks、smartctl 等工具,检测磁盘的硬件问题,或用 e2fsck 等来检测文件系统的错误。如果发现问题,你可以使用 fsck 等工具来修复。