Linux 系统出现了性能问题, 一般我们可以通过 top,iostat,free,vmstat 等命令来查看初步定位问题. 其中 iostat 可以给我们提供丰富的 IO 状态数据.
一, 查询命令基本使用
1, 命令介绍
$iostat -d -k 1 10
-d 表示, 显示设备 (磁盘) 使用状态;
-k 某些使用 block 为单位的列强制使用 Kilobytes 为单位;
1 10 表示, 数据显示每隔 1 秒刷新一次, 共显示 10 次.
2, 用法展示
- # iostat -x 1 10
- Linux 2.6.18-92.el5xen 02/03/2009
- avg-cpu: %user %nice %system %iowait %steal %idle
- 1.10 0.00 4.82 39.54 0.07 54.46
- Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
- sda 0.00 3.50 0.40 2.50 5.60 48.00 18.48 0.00 0.97 0.97 0.28
- sdb 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
- sdd 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- sde 0.00 0.10 0.30 0.20 2.40 2.40 9.60 0.00 1.60 1.60 0.08
- sdf 17.40 0.50 102.00 0.20 12095.20 5.60 118.40 0.70 6.81 2.09 21.36
- sdg 232.40 1.90 379.70 0.50 76451.20 19.20 201.13 4.94 13.78 2.45 93.16
3, 参数讲解
(1)参数如下:
- rrqm/s: 每秒进行 merge 的读操作数目. 即 delta(rmerge)/s
- wrqm/s: 每秒进行 merge 的写操作数目. 即 delta(wmerge)/s
r/s: 每秒完成的读 I/O 设备次数. 即 delta(rio)/s
w/s: 每秒完成的写 I/O 设备次数. 即 delta(wio)/s
- rsec/s: 每秒读扇区数. 即 delta(rsect)/s
- wsec/s: 每秒写扇区数. 即 delta(wsect)/s
rkB/s: 每秒读 K 字节数. 是 rsect/s 的一半, 因为每扇区大小为 512 字节.(需要计算)
wkB/s: 每秒写 K 字节数. 是 wsect/s 的一半.(需要计算)
avgrq-sz: 平均每次设备 I/O 操作的数据大小 (扇区).delta(rsect+wsect)/delta(rio+wio)
avgqu-sz: 平均 I/O 队列长度. 即 delta(aveq)/s/1000 (因为 aveq 的单位为毫秒).
await: 平均每次设备 I/O 操作的等待时间 (毫秒). 即 delta(ruse+wuse)/delta(rio+wio)
svctm: 平均每次设备 I/O 操作的服务时间 (毫秒). 即 delta(use)/delta(rio+wio)
%util: 一秒中有百分之多少的时间用于 I/O 操作, 或者说一秒中有多少时间 I/O 队列是非空的. 即 delta(use)/s/1000 (因为 use 的单位为毫秒)
(2)参数分析:
如果 %util 接近 100%, 说明产生的 I/O 请求太多, I/O 系统已经满负荷, 该磁盘可能存在瓶颈.
await 小于 70% IO 压力就较大了, 一般读取速度有较多的 wait.
同时可以结合 vmstat 查看查看 bi 参数 (等待资源的进程数) 和 wa 参数(IO 等待所占用的 CPU 时间的百分比, 高过 30% 时 IO 压力高)
(3)另外还可以参考, 一般情况:
svctm <await (因为同时等待的请求的等待时间被重复计算了),
svctm 的大小一般和磁盘性能有关: CPU / 内存的负荷也会对其有影响, 请求过多也会间接导致 svctm 的增加.
await: await 的大小一般取决于服务时间(svctm) 以及 I/O 队列的长度和 I/O 请求的发出模式.
如果 svctm 比较接近 await, 说明 I/O 几乎没有等待时间;
如果 await 远大于 svctm, 说明 I/O 队列太长, 应用得到的响应时间变慢,
如果响应时间超过了用户可以容许的范围, 这时可以考虑更换更快的磁盘, 调整内核 elevator 算法, 优化应用, 或者升级 CPU.
队列长度 (avgqu-sz) 也可作为衡量系统 I/O 负荷的指标, 但由于 avgqu-sz 是按照单位时间的平均值, 所以不能反映瞬间的 I/O 洪水.
二, I/O 理解与实例分析
1, 一个不错的例子, 瞬间理解 I/O (I/O 系统 vs. 超市排队)
(1)超市例子:
举一个例子, 我们在超市排队 checkout 时, 怎么决定该去哪个交款台呢? 首当是看排的队人数, 5 个人总比 20 人要快吧? 除了数人头, 我们也常常看看前面人购买的东西多少, 如果前面有个采购了一星期食品的大妈, 那么可以考虑换个队排了. 还有就是收银员的速度了, 如果碰上了连钱都点不清楚的新手, 那就有的等了. 另外, 时机也很重要, 可能 5 分钟前还人满为患的收款台, 现在已是人去楼空, 这时候交款可是很爽啊, 当然, 前提是那过去的 5 分钟里所做的事情比排队要有意义(不过我还没发现什么事情比排队还无聊的).
(2)I/O 系统也和超市排队有很多类似之处
r/s+w/s 类似于交款人的总数
平均队列长度 (avgqu-sz) 类似于单位时间里平均排队人的个数
平均服务时间 (svctm) 类似于收银员的收款速度
平均等待时间 (await) 类似于平均每人的等待时间
平均 I/O 数据 (avgrq-sz) 类似于平均每人所买的东西多少
I/O 操作率 (%util)类似于收款台前有人排队的时间比例.
我们可以根据这些数据分析出 I/O 请求的模式, 以及 I/O 的速度和响应时间.
2, 参数的实例分析
(1)实例
- # iostat -x 1
- avg-cpu: %user %nice %sys %idle
- 16.24 0.00 4.31 79.44
- Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
- /dev/vda 00.00 44.90 1.02 27.55 8.16 579.59 4.08 289.80 20.57 22.35 78.21 5.00 14.29
- /dev/vdb 00.00 44.90 1.02 27.55 8.16 579.59 4.08 289.80 20.57 22.35 78.21 5.00 14.29
- /dev/vbc 00.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
(2)分析
上面的 iostat 输出表明秒有 28.57 次设备 I/O 操作: 总 IO(io)/s = r/s(读) +w/s(写) = 1.02+27.55 = 28.57 (次 / 秒) 其中写操作占了主体 (w:r = 27:1).
平均每次设备 I/O 操作只需要 5ms 就可以完成, 但每个 I/O 请求却需要等上 78ms, 为什么? 因为发出的 I/O 请求太多 (每秒钟约 29 个), 假设这些请求是同时发出的, 那么平均等待时间可以这样计算:
平均等待时间 = 单个 I/O 服务时间 * ( 1 + 2 + ... + 请求总数 - 1) / 请求总数
应用到上面的例子: 平均等待时间 = 5ms * (1+2+...+28)/29 = 70ms, 和 iostat 给出的 78ms 的平均等待时间很接近. 这反过来表明 I/O 是同时发起的.
每秒发出的 I/O 请求很多 (约 29 个), 平均队列却不长 (只有 2 个 左右), 这表明这 29 个请求的到来并不均匀, 大部分时间 I/O 是空闲的.
一秒中有 14.29% 的时间 I/O 队列中是有请求的, 也就是说, 85.71% 的时间里 I/O 系统无事可做, 所有 29 个 I/O 请求都在 142 毫秒之内处理掉了.
delta(ruse+wuse)/delta(io) = await = 78.21 => delta(ruse+wuse)/s=78.21 * delta(io)/s = 78.21*28.57 =2232.8, 表明每秒内的 I/O 请求总共需要等待 2232.8ms. 所以平均队列长度应为 2232.8ms/1000ms = 2.23, 而 iostat 给出的平均队列长度 (avgqu-sz) 却为 22.35, 为什么?! 因为 iostat 中有 bug,avgqu-sz 值应为 2.23, 而不是 22.35.
三, iostat 用法升级
1,Input Output statistics ( iostat )
iostat 反映了终端, 磁盘 I/O 情况和 CPU 活动. 输出结果的第一行是从系统启动到现在为止的这段时间的结果, 接下去的每一行是 interval 时间段内的结果. Kernel 里有一组计数器用来跟踪这些值.
iostat 的默认参数是 tdc(terminal, disk, and CPU). 如果任何其他的选项被指定, 这个默认参数将被完全替代, 例如, iostat -d 将只反映磁盘的统计结果.
2, 语法介绍
基本语法: iostat <options>; interval count
option - 让你指定所需信息的设备, 像磁盘, cpu 或者终端(-d , -c , -t or -tdc ) .x 选项给出了完整的统计结果(gives the extended statistic).
interval - 在两个 samples 之间的时间(秒).
count - 就是需要统计几次
3, 例子
- $ iostat -xtc 5 2
- extended disk statistics tty cpu
- disk r/s w/s Kr/s Kw/s wait actv svc_t %w %b tin tout us sy wt id
- sd0 2.6 3.0 20.7 22.7 0.1 0.2 59.2 6 19 0 84 3 85 11 0
- sd1 4.2 1.0 33.5 8.0 0.0 0.2 47.2 2 23
- sd2 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0
- sd3 10.2 1.6 51.4 12.8 0.1 0.3 31.2 3 31
4, 参数详解
disk: 磁盘名称
r / s: 每秒读取数
w / s: 每秒写入数
Kr / s: 每秒读取的千字节数
Kw / s: 每秒写入的千字节数
等待: 等待服务的平均交易次数(Q 长度)
actv: 正在服务的平均事务数(从队列中删除但尚未完成)
%w: 等待服务的事务的时间百分比(队列非空)
%b: 磁盘忙碌的时间百分比(正在进行的事务)
5, 结果和解决方案
(1)从 iostat 输出结果中需要注意的值:
- Reads/writes per second (r/s , w/s)
- Percentage busy (%b)
- Service time (svc_t)
(2)如果磁盘显示长时间的高 reads/writes, 并且磁盘的 percentage busy (%b)也远大于 5%, 同时 average service time (svc_t)也远大于 30 milliseconds, 这以下的措施需要被执行:
调整应用, 令其使用磁盘 i/o 更加有效率, 可以通过修改磁盘队列, 使用应用服务器的 cache
将文件系统分布到 2 个或多个磁盘上, 并使用 volume manager/disksuite 的条带化特点
增加系统参数值, 如 inode cache , ufs_ninode.Increase the system parameter values for inode cache , ufs_ninode , which is Number of inodes to be held in memory. Inodes are cached globally (for UFS), not on a per-file system basis
将文件系统移到更快的磁盘 / 控制器, 或者用更好的设备来代替
来源: https://www.cnblogs.com/along21/p/9335453.html