剖析生产系统的I/O模式
剖析生产系统的I/O模式
了解I/O的特点对于优化系统性能非常重要,I/O是顺序的还是随机的,是读操作还是写操作,读写的比例是多少,I/O数据块的大小,这些都是影响性能的关键因素。很多存储设备都基于特定的I/O模式做过调校,通用的测试工具跑分都相当漂亮,然而一到实际环境区别就来了,同样的应用环境下,不同的设备表现可能天差地别。我就见过不同厂商的设备,档次差不多,测试跑分高的那个在生产环境下的IO响应速度却慢了十倍。所以跑分高的设备真的不一定适合你的应用。
如果能够模拟出应用的I/O模式,那么在问题复现、乃至设备选型等方面都会有很大帮助。在此之前,了解I/O模式是第一步,这并不容易,像iostat之类的工具只能看到平均值,然而应用系统的I/O请求有可能是波浪式的,一秒之内也可以时高时低,I/O延迟可能平均值不高但是波动很大,而且I/O块大小也可以是变化的,尤其现在大数据应用的块大小可能在很大的范围内变化,与过去常见的交易型数据库有所不同,它们的块大小基本是固定的。
要剖析生产系统的I/O模式,好像没有现成的工具。但是我们可以利用blktrace自己做一个,blktrace在内核的block layer记录每一个I/O,提供了分析的素材。它记录的格式如下:
下面是一个简化版的示例,主要利用了Event “Q”和”C”,分别表示IO开始和IO完成,两者之间的耗时就相当于iostat看到的await,但blktrace可以精确到单个IO:
if [ $# -ne 1 ]; then
echo "Usage: $0 <block_device_name>"
exit
fi
if [ ! -b $1 ]; then
echo "could not find block device $1"
exit
fi
duration=10
echo "running blktrace for $duration seconds to collect data..."
timeout $duration blktrace -d $1 >/dev/null 2>&1
DEVNAME=`basename $1`
echo "parsing blktrace data..."
blkparse -i $DEVNAME |sort -g -k8 -k10 -k4 |awk '
BEGIN {
total_read=0;
total_write=0;
maxwait_read=0;
maxwait_write=0;
}
{
if ($6=="Q") {
queue_ts=$4;
block=$8;
nblock=$10;
rw=$7;
};
if ($6=="C" && $8==block && $10==nblock && $7==rw) {
await=$4-queue_ts;
if (rw=="R") {
if (await>maxwait_read) maxwait_read=await;
total_read++;
read_count_block[nblock]++;
if (await>0.001) read_count1++;
if (await>0.01) read_count10++;
if (await>0.02) read_count20++;
if (await>0.03) read_count30++;
}
if (rw=="W") {
if (await>maxwait_write) maxwait_write=await;
total_write++;
write_count_block[nblock]++;
if (await>0.001) write_count1++;
if (await>0.01) write_count10++;
if (await>0.02) write_count20++;
if (await>0.03) write_count30++;
}
}
} END {
printf("========\nsummary:\n========\n");
printf("total number of reads: %d\n", total_read);
printf("total number of writes: %d\n", total_write);
printf("slowest read : %.6f second\n", maxwait_read);
printf("slowest write: %.6f second\n", maxwait_write);
printf("reads\n> 1ms: %d\n>10ms: %d\n>20ms: %d\n>30ms: %d\n", read_count1, read_count10, read_count20, read_count30);
printf("writes\n> 1ms: %d\n>10ms: %d\n>20ms: %d\n>30ms: %d\n", write_count1, write_count10, write_count20, write_count30);
printf("\nblock size:%16s\n","Read Count");
for (i in read_count_block)
printf("%10d:%16d\n", i, read_count_block[i]);
printf("\nblock size:%16s\n","Write Count");
for (i in write_count_block)
printf("%10d:%16d\n", i, write_count_block[i]);
}'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: $0 <block_device_name>"
exit
fi
if [ ! -b $1 ]; then
echo "could not find block device $1"
exit
fi
duration=10
echo "running blktrace for $duration seconds to collect data..."
timeout $duration blktrace -d $1 >/dev/null 2>&1
DEVNAME=`basename $1`
echo "parsing blktrace data..."
blkparse -i $DEVNAME |sort -g -k8 -k10 -k4 |awk '
BEGIN {
total_read=0;
total_write=0;
maxwait_read=0;
maxwait_write=0;
}
{
if ($6=="Q") {
queue_ts=$4;
block=$8;
nblock=$10;
rw=$7;
};
if ($6=="C" && $8==block && $10==nblock && $7==rw) {
await=$4-queue_ts;
if (rw=="R") {
if (await>maxwait_read) maxwait_read=await;
total_read++;
read_count_block[nblock]++;
if (await>0.001) read_count1++;
if (await>0.01) read_count10++;
if (await>0.02) read_count20++;
if (await>0.03) read_count30++;
}
if (rw=="W") {
if (await>maxwait_write) maxwait_write=await;
total_write++;
write_count_block[nblock]++;
if (await>0.001) write_count1++;
if (await>0.01) write_count10++;
if (await>0.02) write_count20++;
if (await>0.03) write_count30++;
}
}
} END {
printf("========\nsummary:\n========\n");
printf("total number of reads: %d\n", total_read);
printf("total number of writes: %d\n", total_write);
printf("slowest read : %.6f second\n", maxwait_read);
printf("slowest write: %.6f second\n", maxwait_write);
printf("reads\n> 1ms: %d\n>10ms: %d\n>20ms: %d\n>30ms: %d\n", read_count1, read_count10, read_count20, read_count30);
printf("writes\n> 1ms: %d\n>10ms: %d\n>20ms: %d\n>30ms: %d\n", write_count1, write_count10, write_count20, write_count30);
printf("\nblock size:%16s\n","Read Count");
for (i in read_count_block)
printf("%10d:%16d\n", i, read_count_block[i]);
printf("\nblock size:%16s\n","Write Count");
for (i in write_count_block)
printf("%10d:%16d\n", i, write_count_block[i]);
}'
|
输出示例:
summary:
========
total number of reads: 1081513
total number of writes: 0
slowest read : 0.032560 second
slowest write: 0.000000 second
reads
> 1ms: 18253
>10ms: 17058
>20ms: 17045
>30ms: 780
writes
> 1ms: 0
>10ms: 0
>20ms: 0
>30ms: 0
block size: Read Count
256: 93756
248: 1538
64: 98084
56: 7475
8: 101218
48: 15889
240: 1637
232: 1651
224: 1942
40: 21693
216: 1811
32: 197893
208: 1907
24: 37787
128: 97382
16: 399850
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
========
summary:
========
total number of reads: 1081513
total number of writes: 0
slowest read : 0.032560 second
slowest write: 0.000000 second
reads
> 1ms: 18253
>10ms: 17058
>20ms: 17045
>30ms: 780
writes
> 1ms: 0
>10ms: 0
>20ms: 0
>30ms: 0
block size: Read Count
256: 93756
248: 1538
64: 98084
56: 7475
8: 101218
48: 15889
240: 1637
232: 1651
224: 1942
40: 21693
216: 1811
32: 197893
208: 1907
24: 37787
128: 97382
16: 399850
|
这个例子统计了IO的读/写数量、最大延迟、延迟的分布情况、块大小及数量,这些信息比iostat要具体得多,有助于进一步了解系统的IO模式。blktrace数据还有更多的利用空间等待你去发掘,譬如还可以根据时间戳去统计每个毫秒内的IO数,有助于更微观地了解IO请求数量的波动。
转载自:
http://linuxperf.com/?cat=11
剖析生产系统的I/O模式的更多相关文章
- 微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨
sns系统,微博系统都应用到了feed(每条微博或者sns里的新鲜事等我们称作feed)系统,不管是twitter.com或者国内的新浪微博,人人网等,在各种技术社区,技术大会上都在分享自己的feed ...
- 如何设置Win7系统中的上帝模式GodMode(转载)
如何设置Win7系统中的上帝模式GodMode(转载) NT6系统中隐藏了一个秘密的“GodMode”,字面上译为“上帝模式”.God Mode其实就是一个简单的文件夹窗口,但包含了几乎所有系统的设置 ...
- CentOS7+Tomcat 生产系统部署
1 准备OS账户 安全起见,本着最小权限原则,生产系统决不同意使用root账户来执行tomcat.为此,建立新账户tomcat,并设定登录password. useradd tomcat passwd ...
- [置顶] android系统如何在静音模式下关闭camera拍照声音(2)
之前写过一篇“android系统如何在静音模式下关闭camera拍照声音”的博客,今天来写他的续篇,继续探讨这个问题. 公司新需求,要求在camera应用中添加一个开关,可以进行拍照声音的关闭和开启. ...
- runloop是iOS系统上的actor模式
runloop是iOS系统上的actor模式(单线程派发的)
- CentOS修改系统的默认启动模式为命令号界面
CentOS在安装桌面之后,将图形界面设置为默认模式,给PC内存带来较大压力,所以希望修改系统的默认启动模式为命令号界面,而不启动图形界面.方法如下: 1.以 root用户登录系统:或者 用su切换到 ...
- Atitit.biz业务系统 面向框架 面向模式---------数据映射imp
Atitit.biz业务系统 面向框架 面向模式---------数据映射imp 1.1. 面向变量 面向过程 面向对象 面向组件 面向框架 面向服务 面向模式1 1.2. 第2章 架构模式 ...
- JVM性能分析 | 一次生产系统Full GC问题分析与排查总结
一次生产系统Full GC问题分析与排查总结 背景 最近某线上业务系统生产环境频频CPU使用率过低,频繁告警,通过重启可以缓解,但是过了一段时间又会继续预警,线上两个服务节点相继出现CPU资源紧张,导 ...
- 生产系统CPU飙高问题排查
现状 生产系统CPU占用过高,并且进行了报警 排查方法 执行top命令,查看是那个进程导致的,可以确定是pid为22168的java应用导致的 执行top -Hp命令,查看这个进程的那个线程导致cpu ...
随机推荐
- oracle update left join 写法
oracle update left join 写法 (修改某列,条件字段在关联表中) 案例: E:考核表 X,:用户表 USERNAME 关联 需求:修改营业部最高分 分析:通过登录账号的营业部OR ...
- 使用babel es6 转 es5
安装 //Webpack 接入 Babel 必须依赖的模块 npm i -D babel-core babel-loader //preset,告诉babel编译的文件中用到了哪些语法env包含当前所 ...
- C#使用管理员权限打开cmd执行命令行
最近遇到个棘手的问题,服务器远程连不上,但是ftp可以,可能远程连接的服务挂了或者防火墙入站规则有点问题,想要重启,得找机房工作人员,还是挺麻烦的 想了想可以上传个执行cmd命令的东西,然后远程访问触 ...
- PHP Math常量
常量名 常量名 常量值 PHP M_E e 2.7182818284590452354 4 M_EULER Euler 常量 0.57721566490153286061 5.2.0 M_LNPI l ...
- Spring Cloud Alibaba学习笔记(7) - Sentinel规则持久化及生产环境使用
Sentinel 控制台 需要具备下面几个特性: 规则管理及推送,集中管理和推送规则.sentinel-core 提供 API 和扩展接口来接收信息.开发者需要根据自己的环境,选取一个可靠的推送规则方 ...
- Python之(matplotlib、numpy、pandas)数据分析
一.Matplotlib 是一个 Python 的 2D绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形. 它主要用来回事图形,用来展现一些数据,更加直观的展示,让你第一眼就只要数 ...
- 字节数组(byte[])与16进制字符串转换
/// <summary> /// 转换扩展类 /// </summary> public static class ConvertExtend { /// <summa ...
- JavaScript获取页面元素的常用方法
1.通过标签获取元素,返回一个数组 var li = document.getElementsByTagName('li');//标签获取元素 li[0].innerHTML;// 查看获取元素的内容 ...
- SMARTY的知识
smarty的原理: <?php class Smarty { $ldelimiter = "{";//左分隔符 $rdelimiter = "}";// ...
- 转载 AI-Talking 图算法
https://mp.weixin.qq.com/s/2XRgJr-ydxHA3JxAZ_5HeA 图算法在风控业务的实践 直播行业中有很多业务风控问题,比如说批量注册.刷热度.垃圾信息以及薅羊毛等. ...