性能调优-I/O

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40195432/article/details/84852899

I/O
这块是影响系统性能比较大的地方
查看速度:
#hdparm -t /dev/sda
影响I/O性能的因素
1.mount
2.文件系统:日志文件系统和非日志文件系统
3.I/O调度算法
4.RAID,LVM(条带化) 网络附加存储(cpu的iowait转移到存储服务器)
mount
rw ro
***************************************************************

atime noatime   realatime
***************************************************************
Update inode access time for each access. This is the default.
atime是这里影响性能的一个重要因素,可以用noatime关掉
async、sync
***************************************************************
[root@node1 ~]# mount /dev/sdb1 /mnt/
[root@node1 ~]# mount -o remount,sync /dev/sdb1 /mnt/

数据传输3种:
    sync    应用程序产生数据也是写到缓存,但是会等到缓存内的脏数据同步到硬盘之后才会产生新的数据
    async  应用程序把数据写到缓存,操作系统通过伙伴程序kswapd把脏数据写到硬盘,而且会一直产生脏数据,不会等
    directIO直接IO  不会经过缓存,直接往硬盘上写
练习:
使用dd命令测试sync async directIO三种方式谁快谁慢

那么上面3种方式,对应用程序来说,async最快,其次是直接IO,最慢的是同步

问题:
虽然异步对应用程序快了,但是会产生问题,比如脏数据还没来得及全部同步到硬盘,突然断电了,这时候我们称硬盘上的不完整数据被损坏,或者数据不一致

解决:
    断电我们阻止不了,但是我们可以重新写数据,但是现在他怎么知道哪个数据坏了?开机启动的时候使用fsck检测坏块儿

问题:
但是fsck在数据量比较大的时候会非常慢,那怎么解决这个问题?

解决:
    通过Journal日志

在数据写到内存之前先记录一下日志,如果断电重启之后发现哪个写操作没有完成,就通过日志恢复哪个就可以了

有日志以后的数据存储过程:
    写日志
    写数据
    删除日志

ext4可以关掉日志,但是只有在格式化的时候才能关

有日志的话,会变慢,那这个问题如何解决?
创建2个分区,分别格式化为ext2、ext3,dd文件测试速度差异

记录日志的方法:
    #man mount
    Mount options for ext3
    data={journal|ordered|writeback}

    journal最好,但是这种开销最大
    journal 把信息写到缓存,记录日志,记录inode和数据到日志,然后写到硬盘
    ordered 这是默认的模式把信息写到缓存,记录日志,只记录inode,然后写到硬盘
    writeback首先在缓存内把所有的写排好序,然后记录inode,最后写到硬盘 
    
    性能上ordered和writeback差不多

解决记录日志慢问题:
    之所以日志慢:硬盘是一个一个的磁盘片,硬盘效率最高的时候是磁头在某一个磁道不换位置,如果数据不连续也就意味着磁头要来回在日志数据所在的磁道和数据所在的磁道跳换,如果能解决这个问题就OK了。我们可以采用日志分离的方式

    日志分离:
        两块硬盘,一块存日志,一块存数据,必须是两块磁盘,两个分区是不可以的
        #mke2fs -O journal_dev /dev/sdb5   //把这个设备格式化成专门记录日志的设备
        #mkfs.ext3 -J device=/dev/sdb5 /dev/sdb1  //在格式化sdb1的时候声明日志记录在sdb5上,因为是做实验,这里用的是分区
        #mount -o data=journal /dev/sdb1 /mnt/
        在工作当中一般不用日志分离,因为一般我们的服务器上都是raid,所以速度不会慢到哪去,如果不用raid的设备就可能要用到日志分离

各种日志文件系统:
ext3
ext4
jfs IBM的 恢复相当快 AIX
xfs 处理大文件性能特别好
reiserfs suse用的文件系统
btresfs 处理小文件速度特别快

zfs z是26个英文字母的最后一个,寓意在他之后不会再有其他文件系统

rhel7已经放弃ext4了,使用xfs

笔记I/O下面的filesystem下面的实验作为课下作业,但是只能在rhel5里面做,在重启系统的情况下让系统支持xfs,jfs,重点在于给内核添加新功能

I/O 调度算法
查看调度算法 电梯算法

[root@localhost ~]# cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]      //这里是所有的算法,被中括号扩起来的cfq就是默认的调度算法

CFQ (Completely Fair Queuing 完全公平的排队)(elevator=cfq):
    这是默认算法,对于通用服务器来说通常是最好的选择。它试图均匀地分布对I/O带宽的访问。在多媒体应用, 总能保证audio、video及时从磁盘读取数据。但对于其他各类应用表现也很好。每个进程一个queue,每个queue按照上述规则进行merge 和sort。进程之间round robin调度,每次执行一个进程的4个请求。

Deadline (elevator=deadline):
    这个算法试图把每次请求的延迟降至最低。该算法重排了请求的顺序来提高性能。
NOOP (elevator=noop):
    这个算法实现了一个简单FIFO队列。他假定I/O请求由驱动程序或者设备做了优化或者重排了顺序(就像一个智能控制器完成的工作那样)。在有些SAN环境下,这个选择可能是最好选择。适用于随机存取设备, no seek cost,非机械可随机寻址的磁盘。

Anticipatory (elevator=as):
    这个算法推迟I/O请求,希望能对它们进行排序,获得最高的效率。同deadline不同之处在于每次处理完读请求之后, 不是立即返回, 而是等待几个微妙在这段时间内, 任何来自临近区域的请求都被立即执行. 超时以后, 继续原来的处理.基于下面的假设: 几个微妙内, 程序有很大机会提交另一次请求.调度器跟踪每个进程的io读写统计信息, 以获得最佳预期.

APP
app发出请求到下层
buffer cache
io调度器
硬盘

cfq 完全公平队列
a,b,c三个app发出请求, cfq会为每个app准备一个队列,cfg会在每个队列里面一次取4个请求,如果还有剩余请求,继续再取,总之是4个4个的取,他的好处就是每个app都会得到响应
每个app自己的请求可能都是连续的,但是app和app之间他们可能就不会在同一个磁道上,这样就会增加磁头的寻址
所以cfg适用于多媒体或者说桌面级系统

deadline
deadline会把a,b,c的所有请求放到同一个队列,然后对他们进行排序,然后在把统一类型的请求比如读的请求放到fifo里面(fifo就是先进先出)
比如:
a 11 12 13 47
b 31 32 38 39
c 27 28 41 42

deadline
11
12
13
27
28
31
32
38
39
41
42
47
先处理11,然后12,13,。。。。直到最后的47
但是deadline会使a进入饿死状态(比如47),怎样解决 我们会给每一个请求规定一个时间(过了这个时间就饿死了),如果发现某一个请求到时间了,那么停止现在其他所有的操作去处理到达规定时间的那个请求
11
12
13
27
28
31
32
38
39
41
42
47

anticipatory跟deadline差不多,3.0的内核里面已经砍掉了,但是跟deadline不一样的地方是处理11,12,13完事儿之后先等一下,看还有没有14,15如果没有的话再继续

noop直接fifo,谁先来,先处理谁  ssd的硬盘会使用  san存储也会用到

对IO调度使用的建议
Deadline I/O scheduler 使用轮询的调度器,简洁小巧,提供了最小的读取延迟和尚佳的吞吐量,特别适合于读取较多的环境(比如数据库,Oracle 10G 之类).
Anticipatory I/O scheduler 假设一个块设备只有一个物理查找磁头(例如一个单独的SATA硬盘),将多个随机的小写入流合并成一个大写入流,用写入延时换取最大的写入吞吐量.适用于大多数环境,特别是写入较多的环境(比如文件服务器)Web,App等应用我们可以采纳as调度.
CFQ I/O scheduler使用QoS策略为所有任务分配等量的带宽,避免进程被饿死并实现了较低的延迟,可以认为是上述两种调度器的折中.适用于有大量进程的多用户系统

设置调度方法:
linux启动时设置默认IO调度,让系统启动时就使用默认的IO方法,只需在grub.conf文件中加入类似如下行
kernel /vmlinuz-2.6.24 ro root=/dev/sda1 elevator=deadline

条带化
LVM条带化
lvcreate -i 4 -I 64 -n lvtest -L 20G vgtest

RAID
mdadm -C /dev/md0 -l 0 -n 4 -c 16 /dev/sda{7,8,9,10}
mdadm -D /dev/md0
Chunk Size : 16K

查看I/O状态
[root@localhost ~]# sar -d 1 100
Linux 2.6.32-358.el6.x86_64 (mail.robin.com) 2013年11月21日 x86_64 (1 CPU)

22时25分22秒 DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util
22时25分23秒 dev11-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
22时25分23秒 dev8-0 844.58 0.00 10987.95 13.01 0.54 0.65 0.48 40.84
时间 设备主从号 每秒读写请求次数 每秒读多少个扇区 每秒写的扇区个数 平均请求大小 平均队列长度 等待时间

tps 每秒请求数
rd_sec/s 每秒读的扇区数
wr_sec/s 每秒写的扇区数
avgrq-sz 平均每个请求的大小(读写)
avgqu-sz 平均队列长度 队列越长io性能越低
await io请求消耗的平均时间(毫秒) 所有时间(包括等待时间和服务时间) await-svctm=io的等待时间 差值越大 io越繁忙
等待时间:假如现在有块硬盘,处理速度每秒能处理10个请求,那么我现在给他发15个,处理不过来怎么办?排队 await就是从进队列一直到处理完一共用了多长时间
svctm:调度器处理这个排队的请求用了多长时间,比如你排队看医生,医生给你看病花了多长时间
%util io处理io请求所消耗的cpu百分比

[root@localhost ~]# iostat -k
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
scd0 0.00 0.02 0.00 216 0
sda 653.44 28.39 4613.55 365863 59445489

[root@localhost ~]# iostat -x 1
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
scd0 0.00 0.00 0.00 0.00 0.03 0.00 6.86 0.00 2.76 2.76 0.00
sda 2.46 500.26 0.82 651.74 56.41 9215.99 14.21 0.69 1.06 0.73 47.67

rrqm/s 每秒合并的读请求次数
wrqm/s 每秒合并的写请求次数

a对某一个块发出一个读请求,但是现在因为硬盘速度慢,还没来得及处理,结果a又对这个块发出一个读请求,这样我们就可以把这两个读请求合并到一起
a对某一个块发出一个写请求,比如把某一块数据改成123,但是没来得及处理,a又对这个块儿发出一个写请求要把数据改成789,那么这个最后的结果是789,所以我们可以把这两个写请求合并

猜你喜欢

转载自blog.csdn.net/qq_40195432/article/details/84852899
今日推荐