磁盘IO调度算法 -- noop、deadline、cfq

0    2271    1

Tags:

👉 本文共约5872个字,系统预计阅读时间或需23分钟。

文件系统在通过驱动读写磁盘时,不会立即将读写请求发送给驱动,而是延迟执行,这样Linux内核的I/O调度器可以将多个读写请求合并为一个请求或者排序(减少机械磁盘的寻址)发送给驱动,提升性能。工具iostat统计时的值就是由这个过程统计获得(合并统计)。

IO调度器在内核栈中所处位置如下:

磁盘IO调度算法 -- noop、deadline、cfq

I/O 调度算法

I/O 调度算法在各个进程竞争磁盘I/O的时候担当了裁判的角色。他要求请求的次序和时机做最优化的处理,以求得尽可能最好的整体I/O性能。

Linux 4.0 IO协议栈框架图

Linux 4.0 IO协议栈框架图

I/O调度程序的总结:

1)当向设备写入数据块或是从设备读出数据块时,请求都被安置在一个队列中等待完成.

2)每个块设备都有它自己的队列.

3)I/O调度程序负责维护这些队列的顺序,以更有效地利用介质.I/O调度程序将无序的I/O操作变为有序的I/O操作.

4)内核必须首先确定队列中一共有多少个请求,然后才开始进行调度.

single-queue和multi-queue

最新版本的Linux内核已经完全切到multi-queue架构,因此single-queue下的IO调度算法在最新内核可能已经销声匿迹了。但实际上,multi-queue的IO调度算法很大程度上参考了single-queue的IO调度算法,因此一定程度上可以类推

单队列调度算法多队列调度算法
deadlinemq-deadline
cfqbfq
noopnone
kyber

为什么需要IO调度呢?在最开始的时候,Linux存储在磁盘上。磁盘盘片高速旋转,通过磁臂的移动读取数据。磁臂的移动是物理上的机械上的移动,它无法瞬移,这速度是很慢的。如果我们读取的数据位置很随机,一会在A地点,一会在隔着老远的B地点,移动的时间就全做了无用功,这也就是我们说的随机读写性能慢的原因。如果读取的数据地址是连续的,即使不是连续的也是地址接近的,那么移动磁臂的时间损耗就少了。在最开始,IO调度的作用就是为了合并相近的IO请求,减少磁臂的移动损耗。

本人提供Oracle、MySQL、PG等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!

单队列I/O调度的4种算法

单队列架构下,常用的调度算法有3种:noopdeadlinecfq

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

早期Linux 内核的默认调度算法,它给每个进程分配一个调度队列,默认以时间片和请求数限定的方式分配IO资源,以此保证每个进程的 IO 资源占用是公平的。这个算法在IO压力大,且IO主要集中在某几个进程的时候,性能不太友好。

CFQ(Completely Fair Queueing)对于多媒体应用(video,audio)和桌面系统是最好的选择。CFQ赋予I/O请求一个优先级,而I/O优先级请求独立于进程优先级,高优先级的进程的读写不能自动地继承高的I/O优先级。

对于很多IO压力较大的场景就并不是很适应,尤其是IO压力集中在某些进程上的场景。因为这种场景我们需要更多的满足某个或者某几个进程的IO响应速度,而不是让所有的进程公平的使用IO,比如数据库应用。

CFQ试图均匀地分布对I/O带宽的访问,避免进程被饿死并实现较低的延迟,是deadline和as调度器的折中.

工作原理:

CFQ为每个进程/线程,单独创建一个队列来管理该进程所产生的请求,也就是说每个进程一个队列,每个队列按照上述规则进行merge和sort。各队列之间的调度使用时间片来调度,以此来保证每个进程都能被很好的分配到I/O带宽.I/O调度器每次执行一个进程的4次请求。可以调 queued 和 quantum 来优化

NOOP(电梯式调度程序)

NOOP,也叫NONE,是一种简单的FIFO调度策略。

Noop对于I/O不那么操心,对所有的I/O请求都用FIFO队列形式处理,默认认为 I/O不会存在性能问题。这也使得CPU也不用那么操心。它像电梯的工作主法一样对I/O请求进行组织,当有一个新的请求到来时,它将请求合并到最近的请求之后,以此来保证请求同一介质.

NOOP倾向饿死读而利于写.

NOOP对于闪存设备,RAM,嵌入式系统是最好的选择。因为固态硬盘(SSD)支持随机读写,所以固态硬盘可以选择这总最简单的调度策略,性能最好。

电梯算法饿死读请求的解释:

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

Deadline(截止时间调度程序)

通过时间以及硬盘区域进行分类,这个分类和合并要求类似于noop的调度程序.

Deadline确保了在一个截止时间内服务请求,这个截止时间是可调整的,而默认读期限短于写期限.这样就防止了写操作因为不能被读取而饿死的现象.

Deadline对数据库环境(ORACLE RAC,MYSQL等)是最好的选择。

在数据库应用场景中,我们需要更多的满足某个或者某几个进程的IO响应速度,而不是让所有的进程公平的使用IO。deadline调度(最终期限调度)就是更适合这种场景的解决方案。Deadline称为绝对保障算法,是RHEL7的默认I/O算法,适合数据库服务器。

deadline实现了四个队列,其中两个分别处理正常read和write,按扇区号排序,进行正常io的合并处理以提高吞吐量.因为IO请求可能会集中在某些磁盘位置,这样会导致新来的请求一直被合并,于是可能会有其他磁盘位置的io请求被饿死。于是实现了另外两个处理超时read和write的队列,按请求创建时间排序,如果有超时的请求出现,就放进这两个队列,调度算法保证超时(达到最终期限时间)的队列中的请求会优先被处理,防止请求被饿死。

由于deadline的特点,无疑在这里无法区分进程,也就不能实现针对进程的io资源控制。

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

本质上与Deadline一样,但在最后一次读操作后,要等待6ms,才能继续进行对其它I/O请求进行调度.可以从应用程序中预订一个新的读请求,改进读操作的执行,但以一些写操作为代价.它会在每个6ms中插入新的I/O操作,而会将一些小写入流合并成一个大写入流,用写入延时换取最大的写入吞吐量.

AS适合于写入较多的环境,比如文件服务器,AS对数据库环境表现很差。

多队列I/O调度算法

mq-deadline

mq-deadline调度器是根据以前的deadline调度器来的,适配了block层的多队列,基本原理和代码都差不多。

mq-deadline调度器将IO分为read和write两种类型,对于这每种类型的IO有一棵红黑树和一个fifo的队列,红黑树用于将IO按照其访问的LBA排列方便查找合并,fifo队列则记录了io进入mq-deadline调度器的顺序,以提供超时期限的保障。

read类型的IO可以抢write的分发机会,但不可一直抢,有一个计数保证read不会饿死write。

mq-deadline调度器会优先去批量式地分发IO而不去管IO的到期时间,当批量分发到一定的个数再关心到期时间,然后去分发即将到期的IO。

最后mq-deadline针对穿透性IO这种需要尽快发送到设备的IO设置另外一个dispatch队列,然后每次派发的时候都优先派发dispatch队列上的IO。

kyber

none

bfq

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

通过如下命令可以来查到当前系统支持的调度算法:

不同的Linux版本,其默认的I/O调度算法不同,如上是rhel7中的显示,可以看到rhel7的默认的I/O调度算法是deadline。在RHEL6及更老的RHEL版本中,默认的I/O调度算法是cfq。

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

2)临地更改I/O调度方法:

例如:想更改到noop电梯调度算法:

针对PostgreSQL来说,若是$PGDATA在SSD固态盘上,我们推荐的I/O调度算法是noop针对PostgreSQL来说,若是$PGDATA在机械盘上,我们推荐的I/O调度算法是deadline。通过shell命令修改的调度算法,在服务器重启后就会恢复到系统默认值,永久修改调度算法需要修改grub文件。

3)想永久的更改I/O调度方法:

修改内核引导参数,加入elevator=调度程序名

更改到如下内容:

重启之后,查看调度方法:

已经是deadline了

从很多测试结果来看,数据库使用deadline调度,性能会更稳定一些。

一些磁盘相关的内核参数

/sys/block/sda/queue/nr_requests 磁盘队列长度。默认只有 128 个队列,可以提高到 512 个.会更加占用内存,但能更加多的合并读写操作,速度变慢,但能读写更加多的量

/sys/block/sda/queue/iosched/antic_expire 等待时间 。读取附近产生的新请时等待多长时间

/sys/block/sda/queue/read_ahead_kb

这个参数对顺序读非常有用,意思是,一次提前读多少内容,无论实际需要多少.默认一次读 128kb 远小于要读的,设置大些对读大文件非常有用,可以有效的减少读 seek 的次数,这个参数可以使用 blockdev –setra 来设置,setra 设置的是多少个扇区,所以实际的字节是除以2,比如设置 512 ,实际是读 256 个字节.

/proc/sys/vm/dirty_ratio

这个参数控制文件系统的文件系统写缓冲区的大小,单位是百分比,表示系统内存的百分比,表示当写缓冲使用到系统内存多少的时候,开始向磁盘写出数 据.增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能.但是,当你需要持续、恒定的写入场合时,应该降低其数值,一般启动上缺省是 10.下面是增大的方法: echo ’40’>

/proc/sys/vm/dirty_background_ratio

这个参数控制文件系统的pdflush进程,在何时刷新磁盘.单位是百分比,表示系统内存的百分比,意思是当写缓冲使用到系统内存多少的时候, pdflush开始向磁盘写出数据.增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能.但是,当你需要持续、恒定的写入场合时,应该降低其数值,一般启动上缺省是 5.下面是增大的方法: echo ’20’ >

/proc/sys/vm/dirty_writeback_centisecs

这个参数控制内核的脏数据刷新进程pdflush的运行间隔.单位是 1/100 秒.缺省数值是500,也就是 5 秒.如果你的系统是持续地写入动作,那么实际上还是降低这个数值比较好,这样可以把尖峰的写操作削平成多次写操作.设置方法如下: echo ‘200’ > /proc/sys/vm/dirty_writeback_centisecs 如果你的系统是短期地尖峰式的写操作,并且写入数据不大(几十M/次)且内存有比较多富裕,那么应该增大此数值: echo ‘1000’ > /proc/sys/vm/dirty_writeback_centisecs

/proc/sys/vm/dirty_expire_centisecs

这个参数声明Linux内核写缓冲区里面的数据多“旧”了之后,pdflush进程就开始考虑写到磁盘中去.单位是 1/100秒.缺省是 30000,也就是 30 秒的数据就算旧了,将会刷新磁盘.对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,因为缩小太多也会导致IO提高太快.建议设置为 1500,也就是15秒算旧. echo ‘1500’ > /proc/sys/vm/dirty_expire_centisecs 当然,如果你的系统内存比较大,并且写入模式是间歇式的,并且每次写入的数据不大(比如几十M),那么这个值还是大些的好.

总结

  1. 对闪存(SSD)等存储介质,优先使用noop调度算法
  2. 个人PC使用cfq调度算法
  3. 对IO压力比较重,且功能比较单一的场景,例如数据库服务器,使用deadline调度算法
  • 为什么闪存等介质,例如固态硬盘SSD,要选择noop调度算法?
    noop先来先处理的做法对磁盘来说时间损耗非常大,大量浪费了磁盘磁臂移动的时间。但是对闪存设备,例如mmc、nand等,却是最好的选择,因为闪存设备的物理结构跟磁盘完全不同,其通过一些规范的命令即可读取数据,没有磁臂这东西。此时IO调度算法里的排序、合并其实没太大意义,反而浪费了CPU和内存。
  • 为什么个人PC要用cfq调度算法?
    在个人PC的场景上,往往需要打开大量的程序,创建大量的进程。每个进程都可能有IO的请求。在这场景下,我们需要的是如何确保不同进程或进程组间IO资源使用的公平性。总不能因为A进程要拷贝电影,独占了IO资源,导致B进程无法打开文档不是?
    cfq调度算法是以进程之间公平享用IO资源为出发点设计的,所以,个人PC建议使用cfq调度算法,但cfq调度算法不仅仅用于个人PC,准确来说,cfq调度算法适用于有大量进程的多用户系统
  • 为什么deadline调度算法适用于数据库?
    deadline是一种以提高机械硬盘吞吐量为思考出发点的调度算法,所以准确来说,deadline调度算法适用于IO压力比较重,且业务功能单一的场景,而数据库毫无疑问是最为匹配的场景了

参考

https://lwn.net/Articles/738449/

https://blog.csdn.net/juS3Ve/article/details/79693095

https://www.cnblogs.com/gmpy/p/12852449.html

标签:

头像

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

3 × 2 =

 

嘿,我是小麦,需要帮助随时找我哦
  • 18509239930
  • 个人微信

  • 麦老师QQ聊天
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部
返回顶部