IO 性能对于一个系统的影响是相当重要的。一个系统通过多项优化之后,瓶颈每每落在数据库;而数据库通过多种优化之后,瓶颈最终会落到 IO 。而 IO 性能的发展,明显落后于 CPU 的发展。 Memchached 也好, NoSql 也好,这些流行技术的背后都在直接或者间接地回避 IO 瓶颈,从而提升系统性能。html
上图层次比较多,但总的就是三部分。磁盘 (存储)、 VM (卷管理)和文件系统 。专有名词很差理解,打个比方说:磁盘就至关于一块待用的空地; LVM 至关于空地上的围墙(把空地划分红多个部分);文件系统则至关于每块空地上建的楼房(决定了有多少房间、房屋编号如何,能容纳多少人住);而房子里面住的人,则至关于系统里面存的数据。ios
对应了上图的 File System 和 Buffer Cache 。git
File System (文件系统):解决了空间管理的问题 ,即:数据如何存放、读取。github
Buffer Cache :解决数据缓冲的问题。对读,进行 cache ,即:缓存常常要用到的数据;对写,进行buffer ,缓冲必定数据之后,一次性进行写入。数据库
对应上图的 Vol Mgmt 。编程
VM 其实跟 IO 没有必然联系。他是处于文件系统和磁盘(存储)中间的一层。 VM 屏蔽了底层磁盘对上层文件系统的影响 。当没有 VM 的时候,文件系统直接使用存储上的地址空间,所以文件系统直接受限于物理硬盘,这时若是发生磁盘空间不足的状况,对应用而言将是一场噩梦,不得不新增硬盘,而后从新进行数据复制。而 VM 则能够实现动态扩展,而对文件系统没有影响。另外, VM 也能够把多个磁盘合并成一个磁盘,对文件系统呈现统一的地址空间,这个特性的杀伤力不言而喻。缓存
对应上图的 Device Driver 、 IO Channel 和 Disk Device安全
数据最终会放在这里,所以,效率、数据安全、容灾是这里须要考虑的问题。而提升存储的性能,则能够直接提升物理 IO 的性能网络
逻辑 IO 是操做系统发起的 IO ,这个数据可能会放在磁盘上,也可能会放在内存(文件系统的 Cache )里。oracle
物理 IO 是设备驱动发起的 IO ,这个数据最终会落在磁盘上。
逻辑 IO 和物理 IO 不是一一对应的。
这部分的东西在网络编程常常能看到,不过在全部IO处理中都是相似的。
等待资源阶段:IO请求通常须要请求特殊的资源(如磁盘、RAM、文件),当资源被上一个使用者使用没有被释放时,IO请求就会被阻塞,直到可以使用这个资源。
使用资源阶段:真正进行数据接收和发生。
举例说就是排队和服务。
阻塞IO:资源不可用时,IO请求一直阻塞,直到反馈结果(有数据或超时)。
非阻塞IO:资源不可用时,IO请求离开返回,返回数据标识资源不可用
同步IO:应用阻塞在发送或接收数据的状态,直到数据成功传输或返回失败。
异步IO:应用发送或接收数据后马上返回,数据写入OS缓存,由OS完成数据发送或接收,并返回成功或失败的信息给应用。
从性能上看,异步IO的性能无疑是最好的。
阻塞IO:使用简单,但随之而来的问题就是会造成阻塞,须要独立线程配合,而这些线程在大多数时候都是没有进行运算的。Java的BIO使用这种方式,问题带来的问题很明显,一个Socket须要一个独立的线程,所以,会形成线程膨胀。
非阻塞IO:采用轮询方式,不会造成线程的阻塞。Java的NIO使用这种方式,对比BIO的优点很明显,可使用一个线程进行全部Socket的监听(select)。大大减小了线程数。
同步IO:同步IO保证一个IO操做结束以后才会返回,所以同步IO效率会低一些,可是对应用来讲,编程方式会简单。Java的BIO和NIO都是使用这种方式进行数据处理。
异步IO:因为异步IO请求只是写入了缓存,从缓存到硬盘是否成功不可知,所以异步IO至关于把一个IO拆成了两部分,一是发起请求,二是获取处理结果。所以,对应用来讲增长了复杂性。可是异步IO的性能是全部很好的,并且异步的思想贯穿了IT系统放放面面。
最重要的三个指标
IOPS,Input/Output Per Second,即每秒钟处理的I/O请求数量。IOPS是随机访问类型业务(OLTP类)很重要的一个参考指标。
从磁盘上进行数据读取时,比较重要的几个时间是:寻址时间(找到数据块的起始位置),旋转时间(等待磁盘旋转到数据块的起始位置),传输时间(读取数据的时间和返回的时间)。其中寻址时间是固定的(磁头定位到数据的存储的扇区便可),旋转时间受磁盘转速的影响,传输时间受数据量大小的影响和接口类型的影响(不用硬盘接口速度不一样),可是在随机访问类业务中,他的时间也不多。所以,在硬盘接口相同的状况下,IOPS主要受限于寻址时间和传输时间。以一个15K的硬盘为例,寻址时间固定为4ms,传输时间为60s/15000 * 1/2=2ms,忽略传输时间。1000ms/6ms=167个IOPS。
常见磁盘平均物理寻道时间为:
7200RPM(转)/分的STAT硬盘平均物理寻道时间是9ms,平均旋转延迟大约 4.17ms
10000RPM(转)/分的SAS硬盘平均物理寻道时间是6ms ,平均旋转延迟大约 3ms
15000RPM(转)/分的SAS硬盘平均物理寻道时间是4ms,平均旋转延迟大约 2ms
最大IOPS的理论计算方法:IOPS = 1000 ms/ (寻道时间 + 旋转延迟)。忽略数据传输时间。
7200 rpm的磁盘IOPS = 1000 / (9 + 4.17) = 76 IOPS
10000 rpm的磁盘IOPS = 1000 / (6+ 3) = 111 IOPS
15000 rpm的磁盘IOPS = 1000 / (4 + 2) = 166 IOPS
RAID0/RAID5/RAID6的多块磁盘能够并行工做,因此,在这样的硬件条件下, IOPS 相应倍增。假如, 两块15000 rpm 磁盘的话,166 * 2 = 332 IOPS。
维基上列出了常见硬盘的IOPS
SSD 达到了惊人的100,000。 见下图
固态硬盘没有寻道时间和旋转时间。IO耗时是经过地址查找数据耗时,根据芯片颗粒SLC、MLC,中控芯片、队列深度32~6四、接口Sata、PCIE的不一样,通常负载非过高时是相对固定值(控制在60%利用率)。
IOPS = 1000/IO耗时。由于SSD比较固定,好比Intel 320 SSD对8K avgrq-sz耗时0.1ms,1000/0.1ms=10000 IOPS。
在没有文件系统、没有VM(卷管理)、没有RAID、没有存储设备的状况下,这个答案仍是成立的。可是当这么多中间层加进去之后,这个答案就不是这样了。物理硬盘提供的IO是有限的,也是整个IO系统存在瓶颈的最大根源。因此,若是一块硬盘不能提供,那么多块在一块儿并行处理,这不就好了吗?确实是这样的。能够看到,越是高端的存储设备的cache越大,硬盘越多,一方面经过cache异步处理IO,另外一方面经过盘数增长,尽量把一个OS的IO分布到不一样硬盘上,从而提升性能。文件系统则是在cache上会影响,而VM则多是一个IO分布到多个不一样设备上(Striping)。
因此,一个OS的IO在通过多个中间层之后,发生在物理磁盘上的IO是不肯定的。多是一对一个,也可能一个对应多个。
对单块磁盘的IOPS的计算没有没问题,可是当系统后面接的是一个存储系统时、考虑不一样读写比例,IOPS则很难计算,而须要根据实际状况进行测试。主要的因素有:
存储系统自己有本身的缓存。缓存大小直接影响IOPS,理论上说,缓存越大能cache的东西越多,在cache命中率保持的状况下,IOPS会越高。
RAID级别。不一样的RAID级别影响了物理IO的效率。
读写混合比例。对读操做,通常只要cache能足够大,能够大大减小物理IO,而都在cache中进行;对写操做,不论cache有多大,最终的写仍是会落到磁盘上。所以,100%写的IOPS要越狱小于100%的读的IOPS。同时,100%写的IOPS大体等同于存储设备能提供的物理的IOPS。
一次IO请求数据量的多少。一次读写1KB和一次读写1MB,显而易见,结果是彻底不一样的。
当时上面N多因素混合在一块儿之后,IOPS的值就变得扑朔迷离了。因此,通常须要经过实际应用的测试才能得到。
即IO的响应时间。IO响应时间是从操做系统内核发出一个IO请求到接收到IO响应的时间。所以,IO Response time除了包括磁盘获取数据的时间,还包括了操做系统以及在存储系统内部IO等待的时间。通常看,随IOPS增长,由于IO出现等待,IO响应时间也会随之增长。对一个OLTP系统,10ms之内的响应时间,是比较合理的。下面是一些IO性能示例:
须要注意,IOPS与IO Response Time有着密切的联系。通常状况下,IOPS增长,说明IO请求多了,IO Response Time会相应增长。可是会出现IOPS一直增长,可是IO Response Time变得很是慢,超过20ms甚至几十ms,这时候的IOPS虽然还在提升,可是意义已经不大,由于整个IO系统的服务时间已经不可取。
为吞吐量。这个指标衡量标识了最大的数据传输量。如上说明,这个值在顺序访问或者大数据量访问的状况下会比较重要。尤为在大数据量写的时候。
吞吐量不像IOPS影响因素不少,吞吐量通常受限于一些比较固定的因素,如:网络带宽、IO传输接口的带宽、硬盘接口带宽等。通常他的值就等于上面几个地方中某一个的瓶颈。
即单个IO操做请求数据的大小。一次IO操做是指从发出IO请求到返回数据的过程。IO Chunk Size与应用或业务逻辑有着很密切的关系。好比像Oracle一类数据库,因为其block size通常为8K,读取、写入时都此为单位,所以,8K为这个系统主要的IO Chunk Size。IO Chunk Size 小,考验的是IO系统的IOPS能力;IO Chunk Size 大,考验的时候IO系统的IO吞吐量。
熟悉数据库的人都知道,SQL是能够批量提交的,这样能够大大提升操做效率。IO请求也是同样,IO请求能够积累必定数据,而后一次提交到存储系统,这样一些相邻的数据块操做能够进行合并,减小物理IO数。并且Queue Deep如其名,就是设置一块儿提交的IO请求数量的。通常Queue Deep在IO驱动层面上进行配置。
Queue Deep与IOPS有着密切关系。Queue Deep主要考虑批量提交IO请求,天然只有IOPS是瓶颈的时候才会有意义,若是IO都是大IO,磁盘已经成瓶颈,Queue Deep意义也就不大了。通常来讲,IOPS的峰值会随着Queue Deep的增长而增长(不会很是显著),Queue Deep通常小于256。
随机访问的特色是每次IO请求的数据在磁盘上的位置跨度很大(如:分布在不一样的扇区),所以N个很是小的IO请求(如:1K),必须以N次IO请求才能获取到相应的数据。
顺序访问的特色跟随机访问相反,它请求的数据在磁盘的位置是连续的。当系统发起N个很是小的IO请求(如:1K)时,由于一次IO是有代价的,系统会取完整的一块数据(如4K、8K),因此当第一次IO完成时,后续IO请求的数据可能已经有了。这样能够减小IO请求的次数。这也就是所谓的预取。
随机访问和顺序访问一样是有应用决定的。如数据库、小文件的存储的业务,大可能是随机IO。而视频类业务、大文件存取,则大多为顺序IO。
以上各指标中,不用的应用场景须要观察不一样的指标,由于应用场景不一样,有些指标甚至是没有意义的。
随机访问和IOPS: 在随机访问场景下,IOPS每每会到达瓶颈,而这个时候去观察Throughput,则每每远低于理论值。
顺序访问和Throughput:在顺序访问的场景下,Throughput每每会达到瓶颈(磁盘限制或者带宽),而这时候去观察IOPS,每每很小。
与 CPU 不一样,不一样环境下,磁盘的性能指标与厂家标称会不一致。所以,在性能分析前,对所在的计算环境进行标定是颇有必要的。
目前主流的第三方IO测试工具备fio、iometer 和 Orion,这三种工具各有千秋。
fio 在 Linux 系统下使用比较方便,iometer 在 window 系统下使用比较方便,Orion 是 oracle 的IO测试软件,可在没有安装 oracle 数据库的状况下模拟 oracle 数据库场景的读写。
FIO是测试IOPS的很是好的工具,用来对硬件进行压力测试和验证,支持13种不一样的I/O引擎,包括:sync,mmap,libaio,posixaio,SGv3,splice,null,network,syslet,guasi,solarisaio等等。
在FIO官网地址下载最新文件,解压后./configure、make、make install 就可使用fio了。
可使用fio -help查看每一个参数,具体的参数左右能够在官网查看how to文档,以下为几个常见的参数描述
filename=/dev/emcpowerb 支持文件系统或者裸设备,-filename=/dev/sda2或-filename=/dev/sdb direct=1 测试过程绕过机器自带的buffer,使测试结果更真实 rw=randwread 测试随机读的I/O rw=randwrite 测试随机写的I/O rw=randrw 测试随机混合写和读的I/O rw=read 测试顺序读的I/O rw=write 测试顺序写的I/O rw=rw 测试顺序混合写和读的I/O bs=4k 单次io的块文件大小为4k bsrange=512-2048 同上,提定数据块的大小范围 size=5g 本次的测试文件大小为5g,以每次4k的io进行测试 numjobs=30 本次的测试线程为30 runtime=1000 测试时间为1000秒,若是不写则一直将5g文件分4k每次写完为止 ioengine=psync io引擎使用pync方式,若是要使用libaio引擎,须要yum install libaio-devel包 rwmixwrite=30 在混合读写的模式下,写占30% group_reporting 关于显示结果的,汇总每一个进程的信息 此外 lockmem=1g 只使用1g内存进行测试 zero_buffers 用0初始化系统buffer nrfiles=8 每一个进程生成文件的数量
测试场景
100%随机,100%读, 4K fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=rand_100read_4k 100%随机,100%写, 4K fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=rand_100write_4k 100%顺序,100%读 ,4K fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=sqe_100read_4k 100%顺序,100%写 ,4K fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=sqe_100write_4k 100%随机,70%读,30%写 4K fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=randrw_70read_4k
实际测试
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=100 -group_reporting -name=mytest -ioscheduler=noop
上述命令,进行随机读写测试。队列深度为1。
VM (long time running) 是 测试用的虚拟机。这台 VM的磁盘性能极低。只有两位数。同一台 ESXi 上的另外一台 VM(new build ),磁盘性能很正常。二者的区别在于,前者不是新装,而是一直跑 volume test 。后者是新安装的。
用途:主要用于监控系统设备的IO负载状况,iostat首次运行时显示自系统启动开始的各项统计信息,以后运行iostat将显示自上次运行该命令之后的统计信息。用户能够经过指定统计的次数和时间来得到所需的统计信息。
缺点:iostat有一个弱点,就是它不能对某个进程进行深刻分析,仅对系统的总体状况进行分析。iostat属于sysstat软件包。能够用yum install sysstat 直接安装。
命令格式:
iostat[参数][时间][次数]
命令参数: • -C 显示CPU使用状况 • -d 显示磁盘使用状况 • -k 以 KB 为单位显示 • -m 以 M 为单位显示 • -N 显示磁盘阵列(LVM) 信息 • -n 显示NFS 使用状况 • -p[磁盘] 显示磁盘和分区的状况 • -t 显示终端和CPU的信息 • -x 显示详细信息 • -V 显示版本信息
如上图,每1秒钟显示一次报告
iostat -x 2 6 /dev/sda1
每两秒钟显示一次sda1的统计报告,共显示6次。
CPU 属性值
• %user:CPU处在用户模式下的时间百分比。 • %nice:CPU处在带NICE值的用户模式下的时间百分比。 • %system:CPU处在系统模式下的时间百分比。 • %iowait:CPU等待输入输出完成时间的百分比。 • %steal:管理程序维护另外一个虚拟处理器时,虚拟CPU的无心识等待时间百分比。 • %idle:CPU空闲时间百分比。
设备属性值
备注: • 若是%iowait的值太高,表示硬盘存在I/O瓶颈, • %idle值高,表示CPU较空闲, • 若是%idle值高但系统响应慢时,有多是CPU等待分配内存,此时应加大内存容量。 • %idle值若是持续低于10,那么系统的CPU处理能力相对较低,代表系统中最须要解决的资源是CPU。 磁盘每一列的含义以下: • rrqm/s: 每秒进行 merge 的读操做数目。 即 rmerge/s • wrqm/s: 每秒进行 merge 的写操做数目。即 wmerge/s • r/s: 每秒完成的读 I/O 设备次数。 即 rio/s • w/s: 每秒完成的写 I/O 设备次数。即 wio/s • rsec/s: 每秒读扇区数。即 rsect/s • wsec/s: 每秒写扇区数。即 wsect/s • rkB/s: 每秒读 K 字节数。是 rsect/s 的一半,由于扇区大小为 512 字节 • wkB/s: 每秒写 K 字节数。是 wsect/s 的一半 • avgrq-sz: 平均每次设备 I/O 操做的数据大小(扇区) • avgqu-sz: 平均 I/O 队列长度。 • await: 平均每次设备 I/O 操做的等待时间(毫秒) • r_await:每一个读操做平均所需的时间=[Δrd_ticks/Δrd_ios] 不只包括硬盘设备读操做的时间,还包括了在kernel队列中等待的时间。 • w_await:每一个写操做平均所需的时间=[Δwr_ticks/Δwr_ios] 不只包括硬盘设备写操做的时间,还包括了在kernel队列中等待的时间。 • svctm: 平均每次设备 I/O 操做的服务时间(毫秒) • %util: 一秒中有百分之多少的时间用于 I/O 操做,或者说一秒中有多少时间 I/O 队列是非空的。 备注: • 若是 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。 • 若是 svctm 比较接近 await,说明 I/O 几乎没有等待时间; • 若是 await 远大于 svctm,说明I/O 队列太长,io响应太慢,则须要进行必要优化。 • 若是avgqu-sz比较大,也表示有当量io在等待。
在某些场景下,咱们须要找到占用IO特别大的进程,而后关闭它,须要知道PID或者进程名称,这就须要用到iotop。iotop是一个检测Linux系统进程IO的工具,界面相似top,以下图。
iotop和top同样,也能够经过键入相应键,触发排序选项,例如按o能够在IO活动进程和全部进程之间切换。能够经过左右箭头,选择响应的列进行数据排序。
iotop的经常使用参数以下:
-h, --help 查看帮助信息 -o, --only 只查看有IO操做的进程 -b, --batch 非交互模式 -n, --iter= 设置迭代次数 -d, --delay 刷新频率,默认是1秒 -p, --pid 查看指定的进程号的IO,默认是全部进程 -u, --user 查看指定用户进程的IO,默认是全部用户 -P, --processes 只看进程,不看线程 -a, --accumulated 看累计IO,而不是实时IO -k, --kilobytes 以KB为单位查看IO,而不是以最友好的单位显示 -t, --time 每行添加一个时间戳,默认便开启--batch -q, --quit 不显示头部信息
blktrace是一柄神器,不少工具都是基于该神器的:ioprof,seekwatcher,iowatcher,这个工具基本能够知足咱们的对块设备请求的全部了解。
一个I/O请求,从应用层到底层块设备,路径以下图所示:
从上图能够看出IO路径是很复杂的。这么复杂的IO路径咱们是没法用短短一篇小博文介绍清楚的。咱们将IO路径简化一下:
一个I/O请求进入block layer以后,可能会经历下面的过程:
blktrace 可以记录下IO所经历的各个步骤:
咱们一块儿看下blktrace的输出长什么样子:
第一个字段:8,0 这个字段是设备号 major device ID和minor device ID。
第二个字段:3 表示CPU
第三个字段:11 序列号
第四个字段:0.009507758 Time Stamp是时间偏移
第五个字段:PID 本次IO对应的进程ID
第六个字段:Event,这个字段很是重要,反映了IO进行到了那一步
第七个字段:R表示 Read, W是Write,D表示block,B表示Barrier Operation
第八个字段:223490+56,表示的是起始block number 和 number of blocks,即咱们常说的Offset 和 Size
第九个字段: 进程名
其中第六个字段很是有用:每个字母都表明了IO请求所经历的某个阶段。
Q – 即将生成IO请求 | G – IO请求生成 | I – IO请求进入IO Scheduler队列 | D – IO请求进入driver | C – IO请求执行完毕
注意,整个IO路径,分红不少段,每一段开始的时候,都会有一个时间戳,根据上一段开始的时间和下一段开始的时间,就能够获得IO 路径各段花费的时间。
注意,咱们心心念念的service time,也就是反应块设备处理能力的指标,就是从D到C所花费的时间,简称D2C。
而iostat输出中的await,即整个IO从生成请求到IO请求执行完毕,即从Q到C所花费的时间,咱们简称Q2C。
仅仅查看数据进行分析,很是的不直观。工具 iowatcher 能够把 blktrace 采集的信息,转化为图像和动画,方便分析。
iowatcher -t sda.blktrace.bin -o disk.svg iowatcher -t sda.blktrace.bin --movie -o disk.mp4
首先,咱们看 VM volume test 的图像:
说说IO(一)- IO的分层
说说IO(二)- IO模型
说说IO(三)- IO性能的重要指标
说说IO(四)- 文件系统
说说IO(五)- 逻辑卷管理
说说IO(六)- Driver & IO Channel
说说IO(七)- RAID
说说IO(八)- 三分天下
磁盘性能分析
IO测试工具之fio详解
blktrace分析IO