优化-IO
IO子系统
IO,输出输入 input and ouput。
一个IO,指的是从磁盘把数据读出来或者把数据写到磁盘上,就称之为一个IO,一个IO读写的大小为一个OS block.(linux下默认为4096字节,但rhel6的boot分区默认为1024字节)
如何查看块大小?
1,在格式化时 mkfs.ext4 /dev/sda7 --会在格式化的信息里看到
2,使用dumpe2fs
# dumpe2fs /dev/sda1 |grep -i "block size"
dumpe2fs 1.41.12 (17-May-2010)
Block size: 1024 --在rhel6里boot分区默认会为1024
# dumpe2fs /dev/sda7 |grep -i "block size"
dumpe2fs 1.41.12 (17-May-2010)
Block size: 4096 --在rhel6其它分区默认会为4096
3,# stat /boot/grub/grub.conf |head -2 --用stat命令查看一个文件,可以看到此文件所在分区的块大小
File: `/boot/grub/grub.conf'
Size: 1093 Blocks: 6 IO Block: 1024 regular file
iops 顺序io 随机io
block size
IOPS 每秒钟完成多少个IO (io per second)
10k RPM <--每分钟一万转,120 IOPS
15k RPM <--每分钟15000转, 150-200 IOPS
固态硬盘
硬盘的硬件特性我们这里改变不了,但是可以调整OS block大小.
block size 越大,IO吞吐量大,但浪费空间较多
越小,IO吞吐量小,但浪费空间较少
如何改变块大小?
在格式化时使用-b参数指定
如:
# mkfs.ext4 -b 2048 /dev/sda7 --在rhel6.5里测试的可用块大小为1024,2048,4096,8192,16384,32768,65536这几种(8192-65536可以格式化,但挂载不了)
如何优化?
1,买更好更贵的硬盘(如ssd固态硬盘)
2,raid
3,存储多路径
4,lvm(条带卷)
5,分布式存储(云存储)
6,IO调度算法
# iostat
Linux 2.6.32-279.el6.x86_64 (li.cluster.com) 04/25/2014 _x86_64_ (2 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
9.72 0.57 1.34 1.71 0.00 86.66
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sda 24.47 2157.44 43.86 17100165 347648
md127 0.02 0.13 0.00 1016 0
dm-0 0.01 0.08 0.00 672 0
tps 每秒的IO传输次数
Blk_read/s 每秒读了多少个block(一个block单位为512bytes)
Blk_wrtn/s 每秒写了多少个block
Blk_read 两次查看的时间间隔内,一共读了多少块(Blk_read/s乘以两次查看时间间隔秒数),如果只看一次,或者看多次的第一次,是表示从开机到现在读的总量
Blk_wrtn 两次查看的时间间隔内,一共写了多少块(Blk_wrtn/s乘以两次查看时间间隔秒数),如果只看一次,或者看多次的第一次,是表示从开机到现在总的读的总量
# iostat 2 --每两秒显示所有的分区IO状态
# iostat /dev/sda* 2 --每两秒显示所有分区的io状态
# iostat -kx -d sda 2 3
--查看sda的IO状态报告,每两秒打印一次,总共三次 ; -k是表示把默认以每秒多少块显示成每次多少KB;-x打印了一些扩展选项
Linux 2.6.32-279.el6.x86_64 (li.cluster.com) 04/25/2014 _x86_64_ (2 CPU)
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 7.82 4.13 22.09 1.29 1028.68 21.69 89.83 0.15 6.45 2.02 4.72
Device: rrqm/s wrqm/s r/s w/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
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.00 3.50 0.00 3.00 0.00 26.00 17.33 0.02 8.00 7.50 2.25
rrqm/s 每秒的读请求数
wrqm/s 每秒的写请求数
r/s 每秒完成多少个读IO
w/s 每秒完成多少个写IO <-- IOPS=(r/s+w/s)
rsec/s 每秒读取了多少扇区的数据。 一个扇区=512字节数据
wsec/s 每秒写了多少扇区的数据。
rkB/s 每秒读了多少kb数据
wkB/s 每秒写了多少kb数据
avgrq-sz 平均请求数据的大小
avgqu-sz 是平均请求队列的长度。毫无疑问,队列长度越短越好。
await
平均完成IO需要等待多少时间, 包含服务时间,还有在队列中等待的时间。
svctm
服务时间,从IO请求产生到,完成IO的时间。从源代码里可以看出:
(r/s+w/s)*(svctm/1000)=util。
举例子:如果util达到100%,那么此时svctm=1000/(r/s+w/s),
假设IOPS是1000,那么svctm大概在1毫秒左右,如果长时间大于这个数值,
说明系统出了问题。
不过前面已经说过在磁盘阵列等多盘系统中util可能出现偏大的情况,所以svctm相应的也可能偏大。
%util
磁盘带宽使用百分比。如果一直都是100%,说明磁盘很忙。
其它查IO相关的命令
# vmstat
bi:表示读的block数
bo:表示写的block数
# sar -b --可以查看历史的io读写信息
2.6内核四种IO调度算法的区别和比较
# cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq] --默认使用的是cfq算法
5 6 7 8 9 10 100 101
1--------------------------XXX
第N次IO请求 请求地址
1 5
2 100
3 6
4 101
5 7
6 8
7 9
8 10
9 11
noop:大致按照IO请求的时间顺序来处理,先来先处理,但也会做一些相邻IO请求的合并。按上面图处理顺序就可能是1,3,2,4....。但如果请求IO在物理上地址非常随机,则效率不高.
cfq:把IO请求按物理地址排序,按物理地址顺序处理。这样的话磁盘读写效率高,但有可能会造成先请求的IO因为地址太远,而出来等待太久的情况.
deadline:在cfq的基础上加了IO队列来维护等待的IO。如果IO等待过长,超过特定值,会优先处理。
anticipatory:基于预测的IO算法,类似DeadLine,也维护了三个请求对列;区别在于当它处理完一个I/O请求后并不会直接返回处理下一个请求,而是等待6ms(默认),如果这时候有新来的针对当前扇区相邻扇区的请求,那么会直接处理它,当等待时间结束后,调度器才返回处理下一个对列请求
试想一下,如果系统有频繁的针对邻近扇区的I/O请求,那么这种预测算法必然大幅提高整体的吞吐量,毕竟节约了那么多寻道时间
修改方法:
临时改:
echo deadline > /sys/block/sda/queue/scheduler
永久改:
1,把命令放到/etc/rc.local里
2,把elevator=deadline放到grub.conf里kernel参数里(比如放到rhgb quiet后面)