参考文档:

初学 blktrace

blktrace 包包含了很多组件,这次我主要看三个:

安装和预处理

yum install blktrace -y
mount -t debugfs debugfs /sys/kernel/debug

抓数据

mkdir -p ~/blktrace/raw
cd ~/blktrace/raw
blktrace -d /dev/sdi -w 30

然后可以发现产生了一堆原始数据

# ls
sdi.blktrace.0   sdi.blktrace.14  sdi.blktrace.2   sdi.blktrace.4
sdi.blktrace.1   sdi.blktrace.15  sdi.blktrace.20  sdi.blktrace.5
sdi.blktrace.10  sdi.blktrace.16  sdi.blktrace.21  sdi.blktrace.6
sdi.blktrace.11  sdi.blktrace.17  sdi.blktrace.22  sdi.blktrace.7
sdi.blktrace.12  sdi.blktrace.18  sdi.blktrace.23  sdi.blktrace.8
sdi.blktrace.13  sdi.blktrace.19  sdi.blktrace.3   sdi.blktrace.9

CPU 有几个,文件就有几个。看不懂的,但是可以用 blkparse 解析

# blkparse -i sdi | less

里面最有价值的信息在末尾。

"blkparse"

但是我先跳过这个,继续用 btt 工具进一步分析。

btt

把按照 CPU 归档的数据整合成一个大文件:

# blkparse -i sdi -d ../sdi.blktrace.bin
# cd ..

用 btt 分析基本信息

# btt -i sdi.blktrace.bin | less

这时候可读信息就比较多了

"btt1"

IO 生命周期

IO 生命周期要先看

这张图是直接抄这里 http://fibrevillage.com/storage/531-how-to-use-blktrace-and-btt-to-debug-and-tune-disk-io-on-linux

Q------->G------------>I--------->M------------------->D----------------------------->C
|-Q time-|-Insert time-|
|--------- merge time ------------|-merge with other IO|
|----------------scheduler time time-------------------|---driver,adapter,storagetime--|
|----------------------- await time in iostat output ----------------------------------|

大概说就是,一次 IO 完成,有几个阶段

IO 需求生成 -> IO 请求生成(G) -> 进入设备队列(I) -> 同设备 IO 请求按照文件系统优化策略合并成一个大请求(M) -> 请求交付给硬件设备处理(D) -> IO 读写完成(C)

有几个概念一定要看,描述了磁盘从 IO 生成到结束的生命周期:

Q2Q — time between requests sent to the block layer
Q2G — how long it takes from the time a block I/O is queued to the time it gets a request allocated for it
G2I — how long it takes from the time a request is allocated to the time it is Inserted into the device's queue
Q2M — how long it takes from the time a block I/O is queued to the time it gets merged with an existing request
I2D — how long it takes from the time a request is inserted into the device's queue to the time it is actually issued to the device
M2D — how long it takes from the time a block I/O is merged with an exiting request until the request is issued to the device
D2C — service time of the request by the device
Q2C — total time spent in the block layer for a request

参考链接1: http://fibrevillage.com/storage/531-how-to-use-blktrace-and-btt-to-debug-and-tune-disk-io-on-linux

上面是原文。容本菜翻译一下

Q2Q - 两次 IO 请求的时间间隔
Q2G - IO 生成开始进入 IO 队列 到为这个 IO 生成一个完整 IO 请求的时间。
G2I - 完整 IO 请求到该请求插入设备队列的时间
Q2M - IO 生成到在设备队列中和其他 IO 请求合并完成的时间
I2D - IO 生成到 IO请求合并完成并开始交由设备处理的时间
M2D - IO 请求合并完成到开始交由设备处理的时间
D2C - 请求的服务时间,设备真正处理 IO 请求的总时间
Q2C - 块设备层的整体服务时间(我觉得可以理解成从 IO 生成到设备彻底完成请求的总时间,D2C是硬件层面,Q2C是 内核+硬件 层面)

** 不要轻信我,有精力的帮校对下上面英文。**

寻址相关性能 / Device Q2Q Seek Information

Seek 寻址相关有两个栏目

主要指标解释如下

其中 MEAN 地址应该是块设备的逻辑地址,依据是 man btt

--seek-absolute
    When  specified on the command line, this directs btt to calculate seek distances based solely upon the ending block
    address of one IO, and the start of the next.  By default btt uses the concept of the closeness to either the begin‐
    ning or end of the previous IO. See the Users Manual for more details about seek distances.

搜索引擎搜了半天,只有褚霸一份 PPT 提到,但是并没有获得解释,如果我说错了,请指出。

此外寻址中值很多时候会是 0.这是因为机械臂来回寻址,回到了原位。出自:

zero

磨刀不误砍材工,了解了上面概念,我们终于可以有机会去读懂 btt 报告了。

blktrace 实践

经过屡次惨痛的教训,我有了几个体会。

  1. 很多情况下,硬件调优是没有用的,提升并不大。
  2. 试图分析出机械臂摆动和机械臂定位到位置后的写入时间,很难,也意义不大,因为就算你得出来了,也不知道要怎么优化。除非磁盘容量小,方便在不影响业务的情况下做文件系统碎片整理。
  3. 磁盘服务时间,即 DC 指标,磁盘真正接受到 IO 请求到完成 IO 写入的时间,可以作为排出非硬件压力影响,评判磁盘性能的指标。

不同 IO 压力下的 DC 指标变化

硬件信息:

# lspci | grep SAS
02:00.0 RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS-3 3108 [Invader] (rev 02)
# /opt/MegaRAID/MegaCli/MegaCli64 -AdpAllInfo -aALL | grep Mem
Memory           : Present
Memory Size      : 2048MB
Memory Correctable Errors   : 0
Memory Uncorrectable Errors : 0
# smartctl -A /dev/sdf -d megaraid,3
number of hours powered up = 14075.65

我用如下命令组合来获取数据

blktrace -d /dev/sdf -w 30
blkparse -i sdf -d sdf.blktrace.bin
btt -i sdf.blktrace.bin

服务器趋近 0 负载,磁盘趋近 0 负载

blktrace empty

在这种情况下,这台服务器 DC 值为 0.0039 s。

使用 dd + directio 让磁盘带宽满载

dd 命令: dd if=/dev/zero of=/cache3/test.img bs=1M count=10240 oflag=direct

blktrace with dd

可见此时 DC 值为 0.0158 s。

使用 fio 小文件并发测试

fio 命令:fio -filename=/cache3/fio_mix -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=60 -ioengine=libaio -bs=16k -size 2G -numjobs=30 -runtime=60 -group_reporting -name=fio_mix

blktrace with fio

可见此时 DC 值为 0.0727 s。

小结

某公司采购了一批服务器,业务量一直上不去。

有几个现象:

  1. 磁盘 io util% 即服务时间一直趋近 100%
  2. 切走流量后,让磁盘处于趋近空载状态。对任意磁盘施加 IO 压力,会导致其他磁盘 IO util% 也随之增高。

当时推测可能是硬件问题,尤其是点2,重点怀疑是存储控制器问题,这样比较有理由说一个磁盘爆,其他磁盘跟着爆 —— 控制器性能爆掉,导致所有磁盘收到牵连。

通过 blktrace 分析,可以看出 DC 值非常不合理,达到了 0.6s。所以认为硬件处理能力非常弱,异常。

blktracebad

最后阵列卡驱动后,性能趋近于正常,不过还是不满意。

抽了一些不同型号的机器,做了个报表,发现可以看出一些事情。

d2c q2c iops

明显机型 E 有问题。

  1. 其他机型 D2C Q2C 基本都在一个水平线内。
  2. E 机型 Q2C D2C 差异特别大。
  3. E 机型不管是 Q2C 还是 D2C 都远超于其他机器的值。

上述图表采样的时候使用了 fio 做了小文件的压力测试。

机器A 阵列卡型号是 LSI 3108 + 2G 缓存,机器 B 和 机器 C 使用了 LSI 3008 不加缓存。

可看出:

  1. A 和 BC 在单次 IO 请求服务时间上并没有优势
  2. A 和 BC 在总体并发处理上有优势

所以推测结论:阵列卡加缓存可提高并发处理能力,但对个体 IO 并无提升效果。

疑点:机器 B 和 机器 D 使用了同款阵列卡,但是为何 iops 还是有差距呢?

从 DC 图上可以看出,B 和 D 实际硬件响应时间是差不多的。但是在 IOPS 综合表现上却有差距。

基于

  1. 硬盘型号差不多
  2. 阵列卡一致

我的推测是:有其他应用读写磁盘影响。

另外从大文件 dd 上看,可以得出结论:阵列卡对顺序读写并无明显改善效果。

dd