磁盘IO

基本概念:

在数据库优化和存储规划过程中,总会提到IO的一些重要概念,在这里就详细记录一下,个人认为对这个概念的熟悉程度也决定了对数据库与存储优化的理解程度,以下这些概念并非权威文档,权威程度肯定就不能说了。

 

读/写IO:最为常见说法,读IO,就是发指令,从磁盘读取某段扇区的内容。指令一般是通知磁盘开始扇区位置,然后给出需要从这个初始扇区往后读取的连续扇区个数,同时给出动作是读,还是写。磁盘收到这条指令,就会按照指令的要求,读或者写数据。控制器发出的这种指令+数据,就是一次IO,读或者写。

 
大/小块IO:指控制器的指令中给出的连续读取扇区数目的多少,如果数目很大,比如128,64等等,就应该算是大块IO,如果很小,比如1, 4,8等等,就应该算是小块IO,大块和小块之间,没有明确的界限。
 
连续/随机IO:连续和随机,是指本次IO给出的初始扇区地址,和上一次IO的结束扇区地址,是不是完全连续的,或者相隔不多的,如果是,则本次IO应该算是一个连续IO,如果相差太大,则算一次随机IO。连续IO,因为本次初始扇区和上次结束扇区相隔很近,则磁头几乎不用换道或换道时间极短;如果相差太大,则磁头需要很长的换道时间,如果随机IO很多,导致磁头不停换道,效率大大降底。 

顺序/并发IO:这个的意思是,磁盘控制器每一次对磁盘组发出的指令套(指完成一个事物所需要的指令或者数据),是一条还是多条。如果是一条,则控制器缓存中的IO队列,只能一个一个的来,此时是顺序IO;如果控制器可以同时对磁盘组中的多块磁盘,同时发出指令套,则每次就可以执行多个IO,此时就是并发IO模式。并发IO模式提高了效率和速度。
 
IO并发几率:单盘,IO并发几率为0,因为一块磁盘同时只可以进行一次IO。对于raid0,2块盘情况下,条带深度比较大的时候(条带太小不能并发IO,下面会讲到),并发2个IO的几率为1/2。其他情况请自行运算。 

IOPS:即每秒进行读写(I/O)操作的次数,一个IO所用的时间=寻道时间+数据传输时间。 IOPS=IO并发系数/(寻道时间+数据传输时间),由于寻道时间相对传输时间,大几个数量级,所以影响IOPS的关键因素,就是降底寻道时间,而在连续IO的情况下,寻道时间很短,仅在换磁道时候需要寻道。在这个前提下,传输时间越少,IOPS就越高。
 
每秒IO吞吐量。显然,每秒IO吞吐量=IOPS乘以平均IO SIZE。 Io size越大,IOPS越高,每秒IO吞吐量就越高。设磁头每秒读写数据速度为V,V为定值。则IOPS=IO并发系数/(寻道时间+IO SIZE/V),代入,得每秒IO吞吐量=IO并发系数乘IO SIZE乘V/(V乘寻道时间+IO SIZE)。我们可以看出影响每秒IO吞吐量的最大因素,就是IO SIZE和寻道时间,IO SIZE越大,寻道时间越小,吞吐量越高。相比能显著影响IOPS的因素,只有一个,就是寻道时间。
 
重点介绍
 

机械硬盘的连续读写性很好, 但随机读写性能很差。这是因为磁头移动至正确的磁道上需要时间,随机读写时,磁头不停的移动,时间都花在了磁头寻道上,所以性能不高。  如下图:

在存储小文件(图片)、OLTP数据库应用时,随机读写性能(IOPS)是最重要指标。

学习它,有助于我们分析存储系统的性能互瓶颈。
下面我们来认识随机读写性能指标--IOPS(每秒的输入输出次数)。


磁盘性能指标--IOPS
----------------------------------------------------------
        IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。IOPS是指单位时间内系统能处理的I/O请求数量,一般以每秒处理的I/O请求数量为单位,I/O请求通常为读或写数据操作请求。

    随机读写频繁的应用,如小文件存储(图片)、OLTP数据库、邮件服务器,关注随机读写性能,IOPS是关键衡量指标。

    顺序读写频繁的应用,传输大量连续数据,如电视台的视频编辑,视频点播VOD(Video On Demand),关注连续读写性能。数据吞吐量是关键衡量指标。

IOPS和数据吞吐量适用于不同的场合:
读取10000个1KB文件,用时10秒  Throught(吞吐量)=1MB/s ,IOPS=1000  追求IOPS
读取1个10MB文件,用时0.2秒  Throught(吞吐量)=50MB/s, IOPS=5  追求吞吐量

磁盘服务时间
--------------------------------------
传统磁盘本质上一种机械装置,如FC, SAS, SATA磁盘,转速通常为5400/7200/10K/15K rpm不等。影响磁盘的关键因素是磁盘服务时间,即磁盘完成一个I/O请求所花费的时间,它由寻道时间、旋转延迟和数据传输时间三部分构成。

寻道时间 Tseek是指将读写磁头移动至正确的磁道上所需要的时间。寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms。
旋转延迟 Trotation是指盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间。旋转延迟取决于磁盘转速,通常使用磁盘旋转一周所需时间的1/2表示。比如,7200 rpm的磁盘平均旋转延迟大约为60*1000/7200/2 = 4.17ms,而转速为15000 rpm的磁盘其平均旋转延迟为2ms。
数据传输时间 Ttransfer是指完成传输所请求的数据所需要的时间,它取决于数据传输率,其值等于数据大小除以数据传输率。目前IDE/ATA能达到133MB/s,SATA II可达到300MB/s的接口数据传输率,数据传输时间通常远小于前两部分消耗时间。简单计算时可忽略。

常见磁盘平均物理寻道时间为:
7200转/分的STAT硬盘平均物理寻道时间是9ms
10000转/分的STAT硬盘平均物理寻道时间是6ms
15000转/分的SAS硬盘平均物理寻道时间是4ms

常见硬盘的旋转延迟时间为:

7200   rpm的磁盘平均旋转延迟大约为60*1000/7200/2 = 4.17ms

10000 rpm的磁盘平均旋转延迟大约为60*1000/10000/2 = 3ms,

15000 rpm的磁盘其平均旋转延迟约为60*1000/15000/2 = 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


影响测试的因素
-----------------------------------------
实际测量中,IOPS数值会受到很多因素的影响,包括I/O负载特征(读写比例,顺序和随机,工作线程数,队列深度,数据记录大小)、系统配置、操作系统、磁盘驱动等等。因此对比测量磁盘IOPS时,必须在同样的测试基准下进行,即便如此也会产生一定的随机不确定性。


队列深度说明 
NCQ、SCSI TCQ、PATA TCQ和SATA TCQ技术解析 
----------------------------------------
    是一种命令排序技术,一把喂给设备更多的IO请求,让电梯算法和设备有机会来安排合并以及内部并行处理,提高总体效率。
SCSI TCQ的队列深度支持256级
ATA TCQ的队列深度支持32级 (需要8M以上的缓存)
NCQ最高可以支持命令深度级数为32级,NCQ可以最多对32个命令指令进行排序。
    大多数的软件都是属于同步I/O软件,也就是说程序的一次I/O要等到上次I/O操作的完成后才进行,这样在硬盘中同时可能仅只有一个命令,也是无法发挥这个技术的优势,这时队列深度为1。
    随着Intel的超线程技术的普及和应用环境的多任务化,以及异步I/O软件的大量涌现。这项技术可以被应用到了,实际队列深度的增加代表着性能的提高。
在测试时,队列深度为1是主要指标,大多数时候都参考1就可以。实际运行时队列深度也一般不会超过4.


IOPS可细分为如下几个指标:
-----------------------------------------
数据量为n字节,队列深度为k时,随机读取的IOPS
数据量为n字节,队列深度为k时,随机写入的IOPS


IOPS的测试benchmark工具
------------------------------------------
         IOPS的测试benchmark工具主要有Iometer, IoZone, FIO等,可以综合用于测试磁盘在不同情形下的IOPS。对于应用系统,需要首先确定数据的负载特征,然后选择合理的IOPS指标进行测量和对比分析,据此选择合适的存储介质和软件系统

 
 
IO调度策略

一)I/O调度程序的总结:

1)当向设备写入数据块或是从设备读出数据块时,请求都被安置在一个队列中等待完成.
2)每个块设备都有它自己的队列.
3)I/O调度程序负责维护这些队列的顺序,以更有效地利用介质.I/O调度程序将无序的I/O操作变为有序的I/O操作.
4)内核必须首先确定队列中一共有多少个请求,然后才开始进行调度.

二)I/O调度的4种算法

1)CFQ(完全公平排队I/O调度程序)

特点:
在最新的内核版本和发行版中,都选择CFQ做为默认的I/O调度器,对于通用的服务器也是最好的选择.
CFQ试图均匀地分布对I/O带宽的访问,避免进程被饿死并实现较低的延迟,是deadline和as调度器的折中.
CFQ对于多媒体应用(video,audio)和桌面系统是最好的选择.
CFQ赋予I/O请求一个优先级,而I/O优先级请求独立于进程优先级,高优先级的进程的读写不能自动地继承高的I/O优先级.


工作原理:
CFQ为每个进程/线程,单独创建一个队列来管理该进程所产生的请求,也就是说每个进程一个队列,各队列之间的调度使用时间片来调度,
以此来保证每个进程都能被很好的分配到I/O带宽.I/O调度器每次执行一个进程的4次请求.


2)NOOP(电梯式调度程序)

特点:
在Linux2.4或更早的版本的调度程序,那时只有这一种I/O调度算法.
NOOP实现了一个简单的FIFO队列,它像电梯的工作主法一样对I/O请求进行组织,当有一个新的请求到来时,它将请求合并到最近的请求之后,以此来保证请求同一介质.
NOOP倾向饿死读而利于写.
NOOP对于闪存设备,RAM,嵌入式系统是最好的选择.

电梯算法饿死读请求的解释:
因为写请求比读请求更容易.
写请求通过文件系统cache,不需要等一次写完成,就可以开始下一次写操作,写请求通过合并,堆积到I/O队列中.
读请求需要等到它前面所有的读操作完成,才能进行下一次读操作.在读操作之间有几毫秒时间,而写请求在这之间就到来,饿死了后面的读请求.

3)Deadline(截止时间调度程序)

特点:
通过时间以及硬盘区域进行分类,这个分类和合并要求类似于noop的调度程序.
Deadline确保了在一个截止时间内服务请求,这个截止时间是可调整的,而默认读期限短于写期限.这样就防止了写操作因为不能被读取而饿死的现象.
Deadline对数据库环境(ORACLE RAC,MySQL等)是最好的选择.


4)AS(预料I/O调度程序)

特点:
本质上与Deadline一样,但在最后一次读操作后,要等待6ms,才能继续进行对其它I/O请求进行调度.
可以从应用程序中预订一个新的读请求,改进读操作的执行,但以一些写操作为代价.
它会在每个6ms中插入新的I/O操作,而会将一些小写入流合并成一个大写入流,用写入延时换取最大的写入吞吐量.
AS适合于写入较多的环境,比如文件服务器
AS对数据库环境表现很差.

三)I/O调度方法的查看与设置

1)查看当前系统的I/O调度方法:

[root@test1 tmp]# cat /sys/block/sda/queue/scheduler 
noop anticipatory deadline [cfq]

2)临地更改I/O调度方法:
例如:想更改到noop电梯调度算法:
echo noop > /sys/block/sda/queue/scheduler

3)想永久的更改I/O调度方法:
修改内核引导参数,加入elevator=调度程序名
[root@test1 tmp]# vi /boot/grub/menu.lst
更改到如下内容:
kernel /boot/vmlinuz-2.6.18-8.el5 ro root=LABEL=/ elevator=deadline rhgb quiet

重启之后,查看调度方法:
[root@test1 ~]# cat /sys/block/sda/queue/scheduler 
noop anticipatory [deadline] cfq 
已经是deadline了



四)ionice

ionice可以更改任务的类型和优先级,不过只有cfq调度程序可以用ionice.
有三个例子说明ionice的功能:
采用cfq的实时调度,优先级为7
ionice -c1 -n7  -ptime dd if=/dev/sda1 f=/tmp/test bs=2M count=300&
采用缺省的磁盘I/O调度,优先级为3
ionice -c2 -n3  -ptime dd if=/dev/sda1 f=/tmp/test bs=2M count=300&
采用空闲的磁盘调度,优先级为0
ionice -c3 -n0  -ptime dd if=/dev/sda1 f=/tmp/test bs=2M count=300&

ionice的三种调度方法,实时调度最高,其次是缺省的I/O调度,最后是空闲的磁盘调度.
ionice的磁盘调度优先级有8种,最高是0,最低是7.
注意,磁盘调度的优先级与进程nice的优先级没有关系.
一个是针对进程I/O的优先级,一个是针对进程CPU的优先级.

 
磁盘读写能力测试
 
Linux服务器装好系统之后,想要知道硬盘的读写是否能满足服务的需要,如果不满足硬盘的IO就是服务的一个瓶颈。所以我们需要测试硬盘的读写速度,测试的方法很多,下面是使用Linux 自带的dd命令测试硬盘的读写速度。
 
time有计时作用,dd用于复制,从if读出,写到of。if=/dev/zero不产生IO,因此可以用来测试纯写速度。同理of=/dev/null不产生IO,可以用来测试纯读速度。bs是每次读或写的大小,即一个块的大小,count是读写块的数量。
 
测/data目录所在磁盘的纯写速度:
 
[root@nagios ~]# time dd if=/dev/zero of=/var/test bs=8k count=1000000
 1000000+0 records in
 1000000+0 records out
 8192000000 bytes (8.2 GB) copied, 52.5749 seconds, 156 MB/s
 
real    0m55.841s
 user    0m0.507s
 sys    0m15.706s
 
##红色部分是因为使用了time命令才显示的,因此需要time命令来计算复制的时间。
 
测/data目录所在磁盘的纯读速度:
 
[root@nagios ~]# time dd if=/var/test of=/dev/null bs=8k count=1000000
 1000000+0 records in
 1000000+0 records out
 8192000000 bytes (8.2 GB) copied, 49.0088 seconds, 167 MB/s
 
real    0m49.025s
 user    0m0.559s
 sys    0m6.383s
 
测读写速度:
 
[root@nagios ~]# time dd if=/var/test of=/tmp/test bs=8k count=1000000
 125000+0 records in
 125000+0 records out
 8192000000 bytes (8.2 GB) copied, 129.239 seconds, 63.4 MB/s
 
real    2m9.251s
 user    0m0.114s
 sys    0m21.494s
 

备注:理论上测试复制量越大测试结果越准确。
 
正常测试的时候可能不止测试一边,可能会需要很多遍求取平均值,这个测试结果在普通的重定向是没有效果的 之后 google 了一下 用下面的方式重定向到一个文件
 
dd if=/dev/zero of=/var/test bs=8k count=1000000  2>> info
 
这样测试的结果就到info文件里面了

hdparm 测试硬盘读写速度


安装:yum install hdparm

语  法:hdparm [-CfghiIqtTvyYZ][-a <快取分区>][-A <0或1>][-c <I/O模式>][-d <0或1>][-k <0或1>][-K <0或1>][-m <分区数>][-n <0或1>][-p <PIO模式>][-P <分区数>][-r <0或1>][-S <时间>][-u <0或1>][-W <0或1>][-X <传输模式>][设备]

补充说明:hdparm可检测,显示与设定IDE或SCSI硬盘的参数。

参  数:
-a<快取分区> 设定读取文件时,预先存入块区的分区数,若不加上<快取分区>选项,则显示目前的设定。
-A<0或1> 启动或关闭读取文件时的快取功能。
-c<I/O模式> 设定IDE32位I/O模式。
-C 检测IDE硬盘的电源管理模式。
-d<0或1> 设定磁盘的DMA模式。
-f 将内存缓冲区的数据写入硬盘,并清楚缓冲区。
-g 显示硬盘的磁轨,磁头,磁区等参数。
-h 显示帮助。
-i 显示硬盘的硬件规格信息,这些信息是在开机时由硬盘本身所提供。
-I 直接读取硬盘所提供的硬件规格信息。
-k<0或1> 重设硬盘时,保留-dmu参数的设定。
-K<0或1> 重设硬盘时,保留-APSWXZ参数的设定。
-m<磁区数> 设定硬盘多重分区存取的分区数。
-n<0或1> 忽略硬盘写入时所发生的错误。
-p<PIO模式> 设定硬盘的PIO模式。
-P<磁区数> 设定硬盘内部快取的分区数。
-q 在执行后续的参数时,不在屏幕上显示任何信息。
-r<0或1> 设定硬盘的读写模式。
-S<时间> 设定硬盘进入省电模式前的等待时间。
-t 评估硬盘的读取效率。
-T 评估硬盘快取的读取效率。
-u<0或1> 在硬盘存取时,允许其他中断要求同时执行。
-v 显示硬盘的相关设定。
-W<0或1> 设定硬盘的写入快取。
-X<传输模式> 设定硬盘的传输模式。
-y 使IDE硬盘进入省电模式。
-Y 使IDE硬盘进入睡眠模式。
-Z 关闭某些Seagate硬盘的自动省电功能。
测试硬盘的读取速度:

普通磁盘测试:

# hdparm -t /dev/sda
/dev/sda:
Timing buffered disk reads: 316 MB in 3.02 seconds = 104.71 MB/sec

# hdparm -T /dev/sda
/dev/sda:
Timing cached reads: 19328 MB in 1.99 seconds = 9691.24 MB/sec
RAID0测试(两块盘):

# hdparm -t /dev/sdb
/dev/sdb:
Timing buffered disk reads: 622 MB in 3.01 seconds = 206.89 MB/sec

# hdparm -T /dev/sdb1
/dev/sdb1:
Timing cached reads: 19632 MB in 1.99 seconds = 9844.20 MB/sec
RAID0测试(三块盘):

# hdparm -t /dev/sdb
/dev/sdb:
Timing buffered disk reads: 846 MB in 3.00 seconds = 281.54 MB/sec


# hdparm -T /dev/sdb
/dev/sdb:
Timing cached reads: 18412 MB in 1.99 seconds = 9229.67 MB/sec
RAID0测试(四块盘)

/dev/sdb:
Timing cached reads: 19608 MB in 1.99 seconds = 9832.76 MB/sec

Timing buffered disk reads: 860 MB in 3.00 seconds = 286.35 MB/sec
另外ARID卡测试速度后,每次会警告:

HDIO_DRIVE_CMD(null) (wait for flush complete) failed: Inappropriate ioctl for device
参考测试速度方法:time cp -a data2 data2

 
 
如何判断IO达到瓶颈了
 
  如果磁盘IO确实比较大的话,是数据库,可以进行读写分离或者分库操作,减小磁盘压力,文件的话,可以利用raid来减轻压力

查看linux服务器硬盘IO访问负荷的方法:

首先 、用top命令查看

top - 16:15:05 up 6 days, 6:25, 2 users, load average: 1.45, 1.77, 2.14
Tasks: 147 total, 1 running, 146 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.2% us, 0.2% sy, 0.0% ni, 86.9% id, 12.6% wa, 0.0% hi, 0.0% si
Mem: 4037872k total, 4003648k used, 34224k free, 5512k buffers
Swap: 7164948k total, 629192k used, 6535756k free, 3511184k cached

查看12.6% wa

IO等待所占用的CPU时间的百分比,高过30%时IO压力高

其次、 用iostat -x 1 10

avg-cpu: %user %nice %sys %iowait %idle
0.00 0.00 0.25 33.46 66.29

Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.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
sdb 0.00 1122 17.00 9.00 192.00 9216.00 96.00 4608.00 123.79 137.23 1033.43 13.17 100.10
sdc 0.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

查看%util 100.10 %idle 66.29

如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。

idle小于70% IO压力就较大了,一般读取速度有较多的wait.

同时可以结合vmstat 查看查看b参数( 等待资源的进程数 )

vmstat -1


硬盘操作查看工具 iotop

如果你知道有程序在磨你的硬盘,但是你又不能确定是哪一个程序在磨你的硬盘,那么就用 iotop来帮助你吧。

在Ubuntu里安装命令是: sudo apt-get install iotop

安装好之后在终端输入:iotop就可以了

下面来说一具体运用:

可以用左右箭头操作,按 r 是相反方向,按 o 是动态切换

用法 iotop -参数

–version 查看版本信息的

-h, –help 查看帮助信息的

-o, –only 只显示在划硬盘的程序
-b, –batch 批量处理 用来记录日志的

-n NUM 设定循环几次

-d SEC, –delay=SEC 设定显示时间间隔

 
原文地址:https://www.cnblogs.com/xianlai-huang/p/6145137.html