MySQL · 2016-10-16 0

Percona-Toolkit系列之pt-diskstats磁盘性能监控利器

1.pt-diskstats

pt-diskstats是一个perl语言写的脚本,功能和iostat类似,给出磁盘的I/O统计信息。那么它和iostat又有什么不同呢?最大区别在于pt-diskstats可交互,输出信息更加详细,pt-diskstats可以按照不同方式聚合后输出。

pt-diskstats实质上是对/proc/diskstats做snapshot,然后进行相关计算后输出。那么/proc/diskstats又是什么东东呢。我们来捣鼓捣鼓 /proc/diskstats吧,随意取一份主机上的 /proc/diskstats文件下来。

/*忽略上边的一部分,直入主题*/
  8 32 sdc     126    0   1120    144   12691      0       8    173954 0  37879    174095
  8 16 sdb     445  708  24536   4741   16570 270689 2196552    645122 0  51167    649852
  8  0 sda    7775 3587 356010 270169   25407 783088 6366418   1768303 0  96258   2038460
  8  1 sda1    594  242   4688    282       3      0      18         0 0    282       282
  8  2 sda2   7028 3345 350098 269743   12712 783088 6366400   1522774 0  79842   1792506
 11  0 sr0      48    0    384     92       0      0       0         0 0     92        92
 11  1 sr1      45    0    360     64       0      0       0         0 0     64        64
253  0 dm-0  11193    0 370818 342018 1082590      0 8562960 235657930 0 111450 236000126
253  1 dm-1    300    0   2400    919       0      0       0         0 0    516       919

我们以sdc为例:

 8      32 sdc 6722 0 254408 13412 6432 12 5024 242099 0 252445 255511

上面这串字符从左往右依次表示:

8:主设备号,不同类别设备编号不一样,磁盘统一为8

32:次设备号,比如sda的sda为0,sda1位1,sda2为2.也就是一个物理磁盘后面的分区,编号依次递增

sdb:设备名。一般ide接口的以hd[a-d]口命名,scsi和sata接口的以sd[a-z]命名。

下面的十一项解释如下:

Name            units         description
----            -----         -----------
read I/Os       requests      完成的读请求次数
read merges     requests      在IO队列中合并的IO次数,对于机械盘来讲,IO合并对性能帮助太大了,
                              innodb设计中change buffer,double write都有IO合并的影子在里面
read sectors    sectors       读取过的扇区数
read ticks      milliseconds  读取耗费的总时间
write I/Os      requests      完成的写次数
write merges    requests      合并的写次数,write merges/(write I/Os)越大,对IO子系统帮助越大
write sectors   sectors       写入的扇区数
write ticks     milliseconds  写操作耗费的总时间
in_flight       requests      当前的IO请求数
io_ticks        milliseconds  该设备花在实际IO操作上的时间 
time_in_queue   milliseconds  IO请求在该设备上锁耗费的所有时间

pt-diskstats可以工作在两种模式下,第一是工作在交互模式下,该模式下我们可以动态控制pt-diskstats的输出,立刻看到结果,第二种是先收集/proc/diskstats的信息,存到一个文件里面,采集一段时候后再通过pt-diskstats来计算。

2.先采集再分析

这种模式下无人值守,用一个脚本再后台定时采集/proc/diskstats,采集完后我们用工具分析最终结果好了,最后我们可以得出该段时间内的整体IO性能,而不是瞬间的性能指标。

采集脚本如下:

#!/bin/bash
INTERVAL=1
LOOPS=10
INT=1
echo `date`
while (( $INT <= $LOOPS )) 
do
        Sleep=$(date +%s.%N | awk "{print $INTERVAL - (\$1 % $INTERVAL)}")
        sleep $Sleep
        date +"TS %s.%N %F %T" >> diskstats-samples.txt
        cat /proc/diskstats >> diskstats-samples.txt
        let INT=INT+1
done
echo `date`

/*采集时间自己改改LOOPS就好了,采集间隔修改INTERVAL即可,10代表10s*/

采集完后,生成一个很小的文本文件,这是我们可以使用pt-diskstats来对该输出做一些分析,统计出该段时间内,查看每块磁盘的IO活动(–group-disk):

[mysql@hpc02 ~]$ ls -l diskstats-samples.txt 
-rw-rw-r-- 1 mysql mysql 16132 Oct 15 22:52 diskstats-samples.txt
[mysql@hpc02 ~]$ pt-diskstats --group-by disk diskstats-samples.txt 

  #ts device    rd_s rd_avkb rd_mb_s rd_mrg rd_cnc   rd_rt    wr_s wr_avkb wr_mb_s wr_mrg wr_cnc   wr_rt busy in_prg    io_s  qtime stime
  {9} sdc        0.0     0.0     0.0     0%    0.0     0.0   257.5     0.0     0.0     0%    3.7    14.4  54%      0   257.5   12.3   2.1
  {9} sdb        0.0     0.0     0.0     0%    0.0     0.0   278.7     1.2     0.3    18%    4.3    12.7  55%      0   278.7   11.1   1.6
  {9} sda       75.8    23.8     1.8     0%    4.6    60.6   337.6     3.6     1.2    40%    7.2    12.9  88%      0   413.4   17.2   1.4
  {9} sda2      75.8    23.8     1.8     0%    4.6    60.6    80.1    15.4     1.2    74%    1.9     6.3  77%      0   155.9   15.1   2.0
  {9} dm-0      77.3    23.8     1.8     0%    4.6    59.4   639.3     2.4     1.5     0%   14.3    22.3  88%      0   716.5   25.1   1.2

很完美的输出吧,那么我现在就来解释下这些输出到底什么意思,这些输出又比iostat哪里强多少。

#ts:如果按照disk聚合,该值代表到run的总时间,如果按照sample聚合,该值也代表当前run的时间,如果按照all聚合,代表两个快照间时间间隔。关于聚合,后面解释。
device:设备名
rd_s:实际发送到物理设备的读请求次数,该值一般情况下比实际应用请求次数小,因为在IO队列中,很多IO都被合并掉了。
rd_avkb:平均每次读请求的字节,单位KB/s,也就是单词次读数据量
rd_mb_s:该设备上的读取带宽,单位MB/s。ps:rd_s*rd_avkb=rd_mb_s
rd_mrg:被合并的读请求数占总的读请求数的百分比,越高越好
rd_cnc:读请求并发性
rd_rt:读请求平均响应时间
wr_s, wr_avkb, wr_mb_s, wr_mrg, wr_cnc, wr_rt和读请求一样,不赘述
busy:人们习惯称为设备的繁忙程度,暂且这么理解吧
in_prg:当前正在向底层物流设备提交的IO请求数目,如果该值不为0或者很大,那么你的设备负载很重
io_s:IOPS。ps:rd_s+wr_s=ios_s
qtime:IO请求排队时间(IO请求实际发到物理设备前有个排队过程)
stime:物理设备实际做物理读写所耗费的时间

知道每个字段什么意思了,我们现在想查看sdb-sdc两块盘在采集的时间段内的整体IO平均负载情况。

[mysql@hpc02 ~]$ pt-diskstats --group-by disk --devices-regex sd[b-c] diskstats-samples.txt 

  #ts device    rd_s rd_avkb rd_mb_s rd_mrg rd_cnc   rd_rt    wr_s wr_avkb wr_mb_s wr_mrg wr_cnc   wr_rt busy in_prg    io_s  qtime stime
 {59} sdc        5.3    16.0     0.1     0%    0.1    10.6   227.3     4.6     1.0    27%    0.5     1.5  31%      0   232.6    0.7   1.0
 {59} sdb       30.3    16.0     0.5     0%    0.3    10.8   142.9     4.2     0.6     1%    0.5     3.3  51%      0   173.2    1.7   2.9

我还想查看该段时间内sdb的iops变化情况

[mysql@hpc02 ~]$ pt-diskstats --group-by sample --devices-regex sd[b] --columns-regex io_s diskstats-samples.txt 
  #ts device    io_s
  1.0 sdb      200.0
  2.0 sdb      179.7
  3.0 sdb      174.3
  4.0 sdb      164.1
  5.0 sdb      155.8
  6.0 sdb      181.4
  7.0 sdb      187.8
  8.1 sdb      171.2
  9.0 sdb      134.8
 10.0 sdb      150.6
 11.0 sdb      177.0
 12.0 sdb      177.0
 13.0 sdb      152.8
 14.0 sdb      188.6
 15.0 sdb      173.8
 16.0 sdb      151.0
 17.0 sdb      168.0
 18.0 sdb      188.3
 19.0 sdb      204.4
 20.0 sdb      186.8
 21.0 sdb      188.1
 22.0 sdb      190.0
 23.0 sdb      160.0

3.交互模式查看整体IO性能

注意要查看整体性能,我们不能把dm-[0-9]这样的设备算进来,这是就要正则匹配设备名了。又因是查看整体,所以要按照整个snapshot做聚合。

[mysql@hpc02 ~]$ pt-diskstats --devices-regex sd[a-z] --group-by sample
  #ts device    rd_s rd_avkb rd_mb_s rd_mrg rd_cnc   rd_rt    wr_s wr_avkb wr_mb_s wr_mrg wr_cnc   wr_rt busy in_prg    io_s  qtime stime
  0.7 {5}       41.3    16.0     0.6     0%    0.1     9.8   933.5     5.7     5.2    32%    0.3     1.2  31%      1   974.8    0.3   1.1
  1.7 {5}       51.0    16.0     0.8     0%    0.1    10.3   959.6     7.3     6.8    34%    0.2     0.8  25%      0  1010.6    0.3   0.8
  2.7 {5}       55.0    16.0     0.9     0%    0.1    10.0  1000.0     7.0     6.8    34%    0.2     0.6  24%      2  1054.9    0.1   0.8
  3.7 {5}       27.0    16.0     0.4     0%    0.1    26.9   578.8     8.3     4.7    32%    0.4     2.3  41%      2   605.8    0.8   2.3
  4.7 {5}       54.0    16.0     0.8     0%    0.1     9.9  1085.8     6.7     7.1    32%    0.1     0.4  21%      1  1139.7    0.0   0.6
  5.7 {5}       64.0    16.0     1.0     0%    0.1     9.4  1002.6     6.9     6.7    34%    0.2     0.5  24%      0  1066.6    0.1   0.7
  6.7 {5}       53.0    16.0     0.8     0%    0.1     9.5   986.0     6.9     6.7    33%    0.2     0.6  23%      0  1039.0    0.2   0.7
  7.7 {5}       62.0    16.0     1.0     0%    0.1    10.0   854.6     7.3     6.1    31%    0.2     0.8  26%      1   916.6    0.3   1.0

3.1 查看帮助文档

按?就可以看到帮助文档,这些动作可以在改工具运行过程中调整具体配置,而不用停工具,在线调整。很棒吧

  0.8 {5}       51.2    16.0     0.8     0%    0.1    10.8   785.6     9.9     7.6    30%    0.3     1.5  29%      1   836.8    0.7   1.2
  1.8 {5}       47.0    16.0     0.7     0%    0.1    10.7   828.9     7.9     6.4    33%    0.2     0.6  20%      1   875.9    0.2   0.8
   You can control this program by key presses:
   ------------------- Key ------------------- ---- Current Setting ----
   A, D, S) Set the group-by mode              S
   c) Enter a Perl regex to match column names .
   /) Enter a Perl regex to match disk names   sd[a-z]
   z) Set the sample size in seconds           1
   i) Hide inactive disks                      yes
   p) Pause the program
   q) Quit the program
   space) Print headers
   ------------------- Press any key to continue -----------------------

A:每个snapshot每个磁盘设备一行

D:每个磁盘一行

S:一个snapshot只输出一行,所有设备聚合在一起

c:查看某列,比如要查看IOPS。按下c,然后输入ios_s。

/:查看某系列磁盘,例如某些服务器有二三十块磁盘,查看sdf-sdg,只需按下/,然后输入sd[f-g]

z:聚合时间步长,假如5,就表示,1~5,2~6,3~7这样没五秒聚合一次
i:隐藏没有IO活动的设备
p:暂停
q:退出
space:回车是输出表头