RHCA rh442 009 磁盘算法 RAID相关 磁盘压力测试
磁盘
一个数据在磁盘A位置,一个数据在磁盘B位置,他们如果隔着很远。这对磁盘来说性能很差
(机械盘,磁头来回移动)
一个数据写进来,他会把数据放到缓存中,经过磁盘调度算法来调度,最后写到硬盘
io读写与进程优先级没关系。
缓存给磁盘做写操作。与此同时,又有很多读操作,先读还是先写 由调度算法决定
进程优先值再高也与磁盘没关系
blk-mq 多队列
rhel7
cd /sys/block/sda/queue/
只有三种
rhel8
[root@servera queue]# cat scheduler
[mq-deadline] kyber bfq none
[root@servera queue]#
中括号的位置为当前算法
有四种
my-deadline 最终期限 (与红帽7原理一样,只是多队列)
bfq (对应以前cfq)
none (对应noop)
kyber (多出来的)
永久有效可以写在tuned里
[root@servera supermao12]# vi tuned.conf
[root@servera supermao12]# pwd
/usr/lib/tuned/supermao12
[disk]
# The default unit for readahead is KiB. This can be adjusted to sectors
# by specifying the relevant suffix, eg. (readahead => 8192 s). There must
# be at least one space between the number and suffix (if suffix is specified).
readahead=>4096
elevator=bfq
(所有硬盘都一样了,都是bfq)
不同算法调优参数不一样
磁盘算法的优缺点与应用场景
cfq 完全公平排队IO策略
给每一个进程分配一个调度队列,默认以请求片和请求数限定的方式分配IO资源,以此保证每个进程的IO资源占用是公平的。这个算法在IO压力大,且IO主要集中在几个进程的时候,性能不太友好。
适合桌面级,多媒体应用。不适合数据库
cfq 做ppt 搞word 看电影 看qq 看微信 (cfq合适。完全公平,但是没有重点)
deadline
deadline 最终期限调度
对数据库环境是最好的选择,频繁更新小IO环境 (数据库磁盘阵列适合raid10)
在数据库应用场景中,我们需要更多的满足某个或没几个进程的IO相应速度,而不是让所有的进程公平使用IO
deadline有四个队列
有两个处理读写,还有两个处理要超时的,饿死的io
专门有两个处理超时的请求
[root@servera iosched]# cat read_expire
500
[root@servera iosched]# cat write_expire
5000 这是默认值,可以改
[root@servera iosched]# cat fifo_batch
16 #一次性往队列里放多少个IO
读不会超过500ms 写不会超过5000ms (防止超时)
读得快,用户感知很重要
适合小io且多
数据库不要做raid5 raid6
大的IO 可以用raid5 raid6 备份,视频监控
none与noop
无任何调优,先进先出,先来的io先处理,后来后处理
场景一: 如果系统中的硬盘是通过存储映射的LUN /dev/lunsdb
该硬盘所属的存储lun,已经在存储端做过优化,操作系统端就不需要优化,减少cpu压力 (cpu来计算调度算法 减少cpu时钟周期)
场景二:SSD选择none
固态硬盘不需要通过磁盘磁头回移动来进行读写,固态硬盘是通过芯片计算的
io要整合,一次性下发,对固态硬盘来说都不需要了
队列 io整合是在机械硬盘的时代
数据库机械盘应用 deadline 如果有固态选none
kyber
[root@servera iosched]# cat read_lat_nsec
2000000
[root@servera iosched]#
单位纳秒 换算为2毫秒
快速处理请求,快速响应 ssd
适合对于吞吐量敏感
服务器满足几个重要进程就行了(deadline)
windows iometer(网上下)
一个扇区512个字节,10个G就是 10 * 1024 * 1024 * 2 = 20971520
创建一个Access specifications
压力测试4kio 百分之随机写
linux fio
结果
每秒的io总数 30484
每秒119M
平均io响应时间 0.0326
最大io响应时间 1882
cpu使用率 (是否更消耗cpu)
邹老师的机械盘
linux fio
yum -y install fio
fio --name=randwrite --ioengine=libaio --iodepth=1 --rw=randwrite bs=4k --direct=1 --size=512M --numjobs=2 --group_reporting --filename=/tmp/test
--ioengine=libaio (io引擎)
--iodepth=1 (测试车道,一般为1)
--rw=randwrite (随机写)
--direct=1 (直接写io)
--numjobs=2 (2个任务更快,这个和cpu有关,4个cpu设置4) 为1大大降低效率
aio: async io
除此之外有sync
sync更不准,写数据写到硬盘,硬盘给了回应才算写完,才能写下一个io
[root@servera iosched]# fio --name=randwrite --ioengine=libaio --iodepth=1 --rw=randwrite --bs=4k --direct=1 --size=512M --numjobs=2 --group_reporting --filename=/tmp/testfile
randwrite: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=1
...
fio-3.7
Starting 2 processes
randwrite: Laying out IO file (1 file / 512MiB)
Jobs: 1 (f=1): [_(1),w(1)][100.0%][r=0KiB/s,w=13.9MiB/s][r=0,w=3548 IOPS][eta 00m:00s]
randwrite: (groupid=0, jobs=2): err= 0: pid=3781: Wed Jul 6 22:04:41 2022
write: IOPS=7427, BW=29.0MiB/s (30.4MB/s)(1024MiB/35293msec)
slat (usec): min=4, max=24237, avg=38.12, stdev=54.34
clat (usec): min=5, max=25812, avg=220.89, stdev=164.12
lat (usec): min=64, max=25867, avg=259.72, stdev=173.67
clat percentiles (usec):
| 1.00th=[ 74], 5.00th=[ 93], 10.00th=[ 111], 20.00th=[ 133],
| 30.00th=[ 151], 40.00th=[ 169], 50.00th=[ 188], 60.00th=[ 208],
| 70.00th=[ 233], 80.00th=[ 269], 90.00th=[ 359], 95.00th=[ 453],
| 99.00th=[ 881], 99.50th=[ 1074], 99.90th=[ 1450], 99.95th=[ 1631],
| 99.99th=[ 2933]
bw ( KiB/s): min=10064, max=19216, per=51.30%, avg=15240.91, stdev=2053.36, samples=137
iops : min= 2516, max= 4804, avg=3810.18, stdev=513.35, samples=137
lat (usec) : 10=0.01%, 20=0.01%, 50=0.12%, 100=7.01%, 250=68.58%
lat (usec) : 500=20.74%, 750=2.06%, 1000=0.82%
lat (msec) : 2=0.63%, 4=0.02%, 10=0.01%, 50=0.01%
cpu : usr=0.24%, sys=16.53%, ctx=272918, majf=0, minf=61
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,262144,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=29.0MiB/s (30.4MB/s), 29.0MiB/s-29.0MiB/s (30.4MB/s-30.4MB/s), io=1024MiB (1074MB), run=35293-35293msec
Disk stats (read/write):
vda: ios=0/261613, merge=0/0, ticks=0/64564, in_queue=7515, util=99.37%
[root@servera iosched]#
调整算法也可以调高磁盘性能
fifo batch 一次往队列中放入的IO数量,数量越大,性能约好,但延迟变大,反之,设置fifo batch为1,则性能相对于16而已要差,但延迟更小(deadline)
对延迟敏感还是写性能敏感
fio中的I/O延迟包括三种:slat,clat,lat
关系是 lat = slat + clat。
slat 表示fio submit某个I/O的延迟。
clat 表示fio complete某个I/O的延迟。
lat 表示从fio将请求提交给内核,再到内核完成这个I/O为止所需要的时间。
一次性调整三个盘
[disk]
# The default unit for readahead is KiB. This can be adjusted to sectors
# by specifying the relevant suffix, eg. (readahead => 8192 s). There must
# be at least one space between the number and suffix (if suffix is specified).
readahead=>4096
elevator=mq-deadline
[sysfs]
/sys/block/vda/queue/iosched/fifo_batch=2
[root@servera iosched]# ls
fifo_batch front_merges read_expire write_expire writes_starved
[root@servera iosched]# cat fifo_batch
2
[root@servera iosched]# pwd
RAID和文件系统
固态做raid10,raid1 多一些
mdadm -C /dev/md0 -1 raid0 -n 2 /dev/vd[b-c]1
创建软raid
格式化mda
mkfs -t xfs -d su=64k,sw=2 /dev/san/lun1
每满64K就写一次硬盘,每写两个盘。做一次校验
chunk size 条带大小
一个成员盘,写多少个数据,才会移动到下一个磁盘
如果都是大IO,chunk size大小应该和IO对齐,
如果IO很大,chunksize很小。相当于一个chunksize要跨很几个盘,相反
chunksize很大,io小,很多io写在一个地方。那么其他盘就闲住了
sw 数据盘的数量
mkfs.xfs -d su=64k,sw=2 /dev/vdc2
mkfs.xfs -d su=32k,sw=2 /dev/vdc3
一个block 4K * 16 才能写满一个chunksize
往一个成员盘里写16个block
一个条带共32个block (两个数据盘,3个数据盘*3)
chunk size : 64K raid5 四块盘,其中三块数据盘,每块盘写满一个chunksize,即64K。才写下一个成员盘,一个条带有三块数据盘
[root@servera iosched]# mkfs.xfs -d su=32k,sw=3 -f /dev/vdc
meta-data=/dev/vdc isize=512 agcount=8, agsize=163840 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=4096 blocks=1310720, imaxpct=25
= sunit=8 swidth=24 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
就是你的条带设置了32k,然后第一个单元有八个block 写完之后就是第一个磁盘写完了。因为有三块数据盘的缘故 要这样操作三次,所以3 * 8 。得到整个条带宽度24
raid情况下,单盘无需这样设置 (raid需要设置条带,和硬盘数,达到更好的性能)
什么场景ext4,什么场景xfs
xfs更适合大文件
ext4更适合小文件
xfs更消耗cpu
数据库建议用ext4
xfs 默认inodesize 512字节 (可以记录更多额外信息)
ext4 256
也可以指定xfs block inodesize大小
[root@servera iosched]# tune2fs -l xxx (看xfs文件系统)
atime 每24小时更新一次,mtime比atime更新的时候会变
mount -o remount,noatime /
不更改atime
默认的方式下linux会把文件访问的时间atime做记录,文件系统在文件被访问、创建、修改等的时候记录下了文件的一些时间戳,比如:文件创建时间、最近一次修改时间和最近一次访问时间;这在绝大部分的场合都是没有必要的。
因为系统运行的时候要访问大量文件,如果能减少一些动作(比如减少时间戳的记录次数等)将会显著提高磁盘 IO 的效率、提升文件系统的性能。
如果遇到机器IO负载高或是CPU WAIT高的情况,可以尝试使用noatime和nodiratime禁止记录最近一次访问时间戳。
转自honpey
文件系统中 atime,lazytime,relatime 详聊
atime,ctime,mtime是文件inode的三个时间戳,分别表示文件最近一次的访问时间;inode本身的更改(changed)时间;文件数据的更改(modify)时间;这几个概念还是很好区分。ctime和mtime的概念很清楚,每次ctime和mtime变化了,那么这个inode就真的要落盘了,但是atime相对就比较棘手一些;atime表示这个文件被访问(确切的说是读)了,比如cat file操作,但吊诡的是:每次读操作都会转化成一次写,因为atime的改变导致了inode变脏写回。这是很难接受的一件事情,因为哪怕你什么都没有写入,简单的读操作,竟然在系统层面引起了大量的写IO。于是各种优化被提了出来。
noatime:直接没有atime,让系统中的atime失效;relatime:只有当mtime/ctime的时间戳晚于atime的时候才去更新atime;lazytime:如果仅有inode变脏,那么控制inode下发的时间。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
lazytime的问题的本质是:哪些操作会深入到真实的文件系统,那些操作不会深入到真实的文件系统?
比如setsize,write,truncate等操作都是会深入到真实的文件系统中去的,并且这些操作都会使得文件的 i_size 等关键属性发生变化,真实文件系统中会主动把这个 inode 放到到待回写的脏链表(bdi_writeback->b_dirty)中去!但是对于一个cat操作,会引起atime的变化(我们认为atime是一种不关键的inode属性),变化了也就是脏的了,VFS层负责把这个inode放到待回写的脏链表中去(bdi_writeback->b_dirty/b_dirty_time)。这说明,调用mark_inode_dirty让inode回写这件事儿,如果深入到了真实文件系统,比如i_size变了等场景,真实文件系统做;如果未深入到真实文件系统,VFS做!
再引申一件事情:inode结构体中许多重要的成员,比如 i_size, i_links都是在具体文件系统中设置,这个以后慢慢聊
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------那么到这里我们就大致知道了,其实relatime和lazytime其实都是处理的只有atime变化的场景,举例来说:cp file1 file2,此时file1就只有一个atime的变化。这会儿再来看relatime和lazytime,relatime是说atime的改变要与mtime/ctime联系在一起,只有mtime/ctime时间戳晚于atime的时候才会去更新atime,什么意思?初始状态下,我atime是9:00,mtime/ctime是12:00, 我13:00 cat了一下,kernel发现9:00 < 12:00,于是把atime更新为13:00;初始状态下,我atime是9:00,mtime/ctime是8:00,我13:00 cat了一下,kernel发现9:00 > 8:00,那么便不会更新atime,atime此时仍为9:00,这是relatime。lazytime呢,是说我inode的atime是实时更新的,8:00 cat,那么atime是8:00,13:00 cat,atime就变成了13:00,但是如果设置了lazytime,这个只有atime变化的inode是不会被下发的,只有当如下条件之一发生时才会被下发:1)有其他重要属性变化,如i_size/i_links等;2)如果用户态调用fsync/fdatasync等。
通过这些分析知道,lazytime 和 relatime 会大量减少IO的数量。好了,这就是基本的原理咯。
最后看如何使能这些标记:
mount -t ext4 -oremount,lazytime /dev/ram0 ext4
mount -t ext4 -oremount,relatime /dev/ram0 ext4
mount-t ext4 -oremount,strictatime /dev/ram0 ext4
mount -t ext4 -oremount,noatime /dev/ram0 ext4