1.3 磁盘
iostat 使用
使用:
iostat [options] [<interval> [<count>]]
比如间隔 2 每秒展示一次统计数据,总共展示 20 次:
iostat -x -p 2 20
参数 options 与含义:
-x 显示详细信息
-p[磁盘] 显示磁盘和分区的情况
-C 显示CPU使用情况
-d 显示磁盘使用情况
-k 以 KB 为单位显示
-m 以 M 为单位显示
-N 显示磁盘阵列(LVM) 信息
-t 显示终端和CPU的信息
-V 显示版本信息
显示每一列的含义:
rrqm/s和wrqm/s(read request merged, write request merged):每秒合并的读和写请求。如果请求队列中多个逻辑请求的地址位于相邻/同一个块,操作系统会将这些请求合并为一个请求到实际磁盘。一般顺序访问相比随机访问会出现更多的合并数r/s:每秒发送到设备的读请求数(合并之后的数值)w/s:每秒发送到设备的写请求数(合并之后的数值)rkB/s: 每秒读数据量(kB为单位)wkB/s: 每秒写数据量(kB为单位)rsec/s和wsec/s:每秒读和写的扇区数(每扇区大小为512字节)avgrq–sz:平均每次 IO 请求的扇区数avgqu–sz:平均在设备队列中等待的 IO 请求数await:平均每个 IO 请求花费的时间(等待时间与处理时间,单位为 ms)r_await和w_await: 平均每个 IO 读请求与写请求的所花费的时间svctm:平均每个 IO 请求(服务)处理时间 这项指标不可信,将被废弃%util:采集周期内有 IO 处理的时间比率,即 IO 队列非空的时间比率。(这里有 IO 处理没有考虑 IO 有多少,只考虑有没有,一般块设备可以并发处理请求,所以单纯看这个值并不能说明设备处理是否饱和)
注意:iostat 从 /proc/diskstats 获取信息,计算得到展示数据。/proc/diskstats 提供的是累计值,展示的数据需要计算时间间隔前后的变化,所以 iostat 运行首次输出的是自系统启动开始到现在的各项统计信息,之后才显示自上次输出到现在的统计信息
IO 使用率 = 采集周期内 IO 处理时长/采集周期时长 假设采集周期为 1000ms,则 %util = (r/s + w/s) * svctm / 1000
常见 linux 的磁盘 IO 指标的缩写习惯: - rq 是 request - r 是 read - w 是 write - qu 是 queue - sz 是 size - a 是 average - tm 是 time - svc 是 service。
/proc/diskstats
$ cat /proc/diskstats
8 0 sda 284582428 3662549 46775621561 463232949 331115798 379042858 23932284589 1218204980 0 1137934235 1949683834
8 1 sda1 22 0 176 248 0 0 0 0 0 256 256
8 2 sda2 31919620 529912 1308796698 168580225 3802763 484906 37468832 3650707 0 102423621 187605638
8 3 sda3 1903036 20859 112724155 11083792 7317913 295559 67078769 7332650 0 14976486 23037140
8 4 sda4 19758029 135050 2122710340 29034910 78120710 6565898 1001751842 54812811 0 81205754 132614573
/proc/diskstats 有 14 个字段,除了 in_flight 字段外都是累计值,从系统启动之后一直累加,按顺序分别为:
major_dev_numminor_dev_num-
device -
read_ios: 读操作的次数。 read_merges: 合并读操作的次数。如果两个读操作读取相邻的数据块时,可以被合并成一个,以提高效率。合并的操作通常是 I/O scheduler(也叫elevator)负责的。read_sectors: 读取的扇区数量(每个扇区 512 字节)。-
read_ticks: 读操作消耗的时间(以毫秒为单位),包括了在队列中等待的时间。 -
write_ios: 写操作的次数。 write_merges: 合并写操作的次数。write_sectors: 写入的扇区数量。-
write_ticks: 写操作消耗的时间(以毫秒为单位)。 -
in_flight: 当前未完成的 I/O 数量。在 I/O 请求进入队列时该值加 1,在 I/O 结束时该值减 1。注意:是 I/O 请求进入队列时,而不是提交给硬盘设备时。 io_ticks: 该设备用于处理 I/O 的自然时间(wall-clock time),单位:ms。请注意io_ticks与read_ticks和write_ticks的区别,read_ticks和write_ticks是把每一个 I/O 所消耗的时间累加在一起,因为硬盘设备通常可以并行处理多个 I/O,所以read_ticks和write_ticks往往会比自然时间大。而io_ticks表示该设备有 I/O(即非空闲)的时间,不考虑 I/O 有多少,只考虑有没有。在实际计算时,字段in_flight不为零的时候io_ticks保持计时,字段in_flight为零的时候io_ticks停止计时。time_in_queue: 对io_ticks的加权值。io_ticks是自然时间,不考虑当前有几个 I/O,而time_in_queue是用当前的 I/O 数量(即字段in-flight)乘以自然时间。虽然该字段的名称是time_in_queue,但并不真的只是在队列中的时间,其中还包含了硬盘处理 I/O 的时间。iostat 在计算avgqu-sz时会用到这个字段。
监控项:
- 每秒读 io 次数:r/s = Δread_ios / Δt
- 每秒写 io 次数:w/s = Δwrite_ios / Δt
- 每秒读字节数:Δread_sectors * 512 / Δt
- 每秒写字节数:Δwrite_sectors * 512 / Δt
- 每个读操作平均所需的时间: r_await = Δread_ticks / Δread_ios > 不仅包括硬盘设备读操作的时间,还包括了在 kernel 队列中等待的时间。
- 每个写操作平均所需的时间: w_await = Δwrite_ticks / Δwrite_ios > 不仅包括硬盘设备写操作的时间,还包括了在 kernel 队列中等待的时间。
- 该硬盘设备的繁忙比率: %util = Δio_ticks / Δt > 表示该设备有I/O(即非空闲)的时间比率,不考虑I/O有多少,只考虑有没有。
测试磁盘 IO
$ dd if=/dev/zero of=/data/disk1/test bs=1M count=65536 oflag=direct
65536+0 records in
65536+0 records out
68719476736 bytes (69 GB) copied, 459.304 s, 150 MB/s
磁盘空间
$ df -h
- 磁盘的 total size != used + avail
- use% = used / (used + avail)
使用 java 计算 df 展示的指标:
|------------- free ----------|
|-------usable------|----used-----|
|-reserve-|
|xxxxxxxxx|+++++++++++++++++++|=============|
|---------------- total --------------------|
File file = new File("/");
// 总空间,单位 byte
long total = file.getTotalSpace();
// 可用空间,单位 byte
long usable = file.getUsableSpace();
保留空间
保留空间默认 5%,用来避免系统进程以及文件系统优化,超级用户在磁盘写满的情况下仍有足够的空间来修复问题。
查看保留空间:
$ tune2fs -l /dev/vdb | grep "Reserved block count"
查看块大小:
$ tune2fs -l /dev/vdb | grep "Block size"
修改保留空间比例:
$ tune2fs -m 1 /dev/vdb
tune2fs 1.42.9 (28-Dec-2013)
Setting reserved blocks percentage to 1% (262144 blocks)
完全去掉保留空间
$ tune2fs -m 0 /dev/vdb
tune2fs 1.42.9 (28-Dec-2013)
Setting reserved blocks percentage to 0% (0 blocks)
https://askubuntu.com/questions/249387/df-h-used-space-avail-free-space-is-less-than-the-total-size-of-home
https://stackoverflow.com/a/76363346/7417992
/proc/mounts
$ cat /proc/mounts
/dev/vda1 / ext4 rw,relatime,data=ordered 0 0
/dev/vdb /data/disk1 ext4 rw,relatime,data=ordered 0 0
/dev/vdc /data/disk2 ext4 rw,relatime,data=ordered 0 0
每一列字段含义为:
- device
- mount point
- file-system type
- read-only / read-write
- dummy values
/proc/sys/fs/
$ cat /proc/sys/fs/file-nr
1920 0 6553500
表示系统支持最多文件数为 6553500 个,当前已用 1920 个文件
参考
- 容易被误读的IOSTAT: http://linuxperf.com/?p=156
- https://blog.csdn.net/MrSate/article/details/104421383
- https://tech.meituan.com/2017/05/19/about-desk-io.html
- https://gist.github.com/mmalone/1081615/a37b09ce1d6ac6960742444c50f99728bffc9859
- https://github.com/prometheus/node_exporter/blob/v1.3.1/collector/filesystem_linux.go
- https://www.robustperception.io/kernel-file-descriptor-metrics-from-the-node-exporter/
- https://www.robustperception.io/dealing-with-too-many-open-files/
- https://www.orchome.com/1445
- https://github.com/prometheus/node_exporter/blob/v1.3.1/collector/filefd_linux.go