Linux·内核的 4 大 IO 调度算法

这篇具有很好参考价值的文章主要介绍了Linux·内核的 4 大 IO 调度算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Linux 内核包含4个IO调度器,分别是 Noop IO scheduler、Anticipatory IO scheduler、Deadline IO scheduler 与 CFQ IO scheduler。

anticipatory, 预期的;提早发生的;期待着的

通常磁盘的读写影响是由磁头到柱面移动造成了延迟,解决这种延迟内核主要采用两种策略:缓存和IO调度算法来进行弥补.

本文做一简单介绍.

调度算法概念

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

Linux·内核的 4 大 IO 调度算法

IO调度器(IO Scheduler)

Linux·内核的 4 大 IO 调度算法

IO调度器(IO Scheduler)是操作系统用来决定块设备上IO操作提交顺序的方法。存在的目的有两个,一是提高IO吞吐量,二是降低IO响应时间。然而IO吞吐量和IO响应时间往往是矛盾的,为了尽量平衡这两者,IO调度器提供了多种调度算法来适应不同的IO请求场景。其中,对数据库这种随机读写的场景最有利的算法是DEANLINE。

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

Linux·内核的 4 大 IO 调度算法

Linux·内核的 4 大 IO 调度算法

块设备最悲剧的地方就是磁盘转动,这个过程会很耗时间。 每个块设备或者块设备的分区,都对应有自身的请求队列(request_queue),而每个请求队列都可以选择一个I/O调度器来协调所递交的request。I/O调度器的基本目的是将请求按照它们对应在块设备上的扇区号进行排列,以减少磁头的移动,提高效率。每个设备的请求队列里的请求将按顺序被响应。实际上,除了这个队列,每个调度器自身都维护有不同数量的队列,用来对递交上来的request进行处理,而排在队列最前面的request将适时被移动到请求队列中等待响应。

Linux·内核的 4 大 IO 调度算法

IO scheduler 的作用主要是为了减少磁盘转动的需求。主要通过2中方式实现:

1.合并 2.排序

每个设备都会自己对应请求队列,所有的请求在被处理之前都会在请求队列上。 在新来一个请求的时候如果发现这个请求和前面的某个请求请求的位置是相邻的,那么就可以合并为一个请求。如果不能找到合并的,就会按照磁盘的转动方向进行排序。通常IO scheduler 的作用就是为了在进行合并和排序的同时,也不会太影响单个请求的处理时间。

1、NOOP

Linux·内核的 4 大 IO 调度算法

FIFO

  1. noop是什么? noop是一种输入输出调度算法 . NOOP, No Operation. 什么都不做,请求来一个处理一个。这种方式事实起来简单,也更有效。问题就是disk seek 太多,对于传统磁盘,这是不能接受的。 但对于SSD 磁盘就可以,因为SSD 磁盘不需要转动。
  2. noop的别称 又称为电梯调度算法.
  3. noop原理是怎样的?

将输入输出请求放到一个FIFO队列中,然后按次序执行队列中的输入输出请求:

当来一个新请求时:

  1. 如果能合并就合并
  2. 如果不能合并,就会尝试排序。 如果队列上的请求都已经很老了,这个新的请求就不能插队,只能放到最后面。否则就插到合适的位置
  3. 如果既不能合并,有没有合适的位置插入,就放到请求队列的最后。
  4. 适用场景

4.1 在不希望修改输入输出请求先后顺序的场景下;   4.2 在输入输出之下具有更加智能调度算法的设备,如NAS存储设备;   4.3 上层应用程序已经精心优化过的输入输出请求;   4.4 非旋转磁头式的磁盘设备,如SSD磁盘

2、CFQ(Completely Fair Queuing, 完全公平排队)

CFQ(Completely Fair Queuing)算法,顾名思义,绝对公平算法。它试图为竞争块设备使用权的所有进程分配一个请求队列和一个时间片,在调度器分配给进程的时间片内,进程可以将其读写请求发送给底层块设备,当进程的时间片消耗完,进程的请求队列将被挂起,等待调度。

每个进程的时间片和每个进程的队列长度取决于进程的IO优先级,每个进程都会有一个IO优先级,CFQ调度器将会将其作为考虑的因素之一,来确定该进程的请求队列何时可以获取块设备的使用权。

IO优先级从高到低可以分为三大类:

RT(real time) BE(best try) IDLE(idle)

其中RT和BE又可以再划分为8个子优先级。可以通过ionice 去查看和修改。 优先级越高,被处理的越早,用于这个进程的时间片也越多,一次处理的请求数也会越多。

实际上,我们已经知道CFQ调度器的公平是针对于进程而言的,而只有同步请求(read或syn write)才是针对进程而存在的,他们会放入进程自身的请求队列,而所有同优先级的异步请求,无论来自于哪个进程,都会被放入公共的队列,异步请求的队列总共有8(RT)+8(BE)+1(IDLE)=17个。

从Linux 2.6.18起,CFQ作为默认的IO调度算法。对于通用的服务器来说,CFQ是较好的选择。具体使用哪种调度算法还是要根据具体的业务场景去做足benchmark来选择,不能仅靠别人的文字来决定。

3、DEADLINE

DEADLINE在CFQ的基础上,解决了IO请求饿死的极端情况。

除了CFQ本身具有的IO排序队列之外,DEADLINE额外分别为读IO和写IO提供了FIFO队列。

Linux·内核的 4 大 IO 调度算法

读FIFO队列的最大等待时间为500ms,写FIFO队列的最大等待时间为5s(当然这些参数都是可以手动设置的)。

FIFO队列内的IO请求优先级要比CFQ队列中的高,,而读FIFO队列的优先级又比写FIFO队列的优先级高。优先级可以表示如下:

FIFO(Read) > FIFO(Write) > CFQ

deadline 算法保证对于既定的 IO 请求以最小的延迟时间,从这一点理解,对于 DSS 应用应该会是很适合的。

deadline 实际上是对Elevator 的一种改进: 1 避免有些请求太长时间不能被处理。 2 区分对待读操作和写操作。

deadline IO 维护3个队列。第一个队列和Elevator 一样, 尽量按照物理位置排序。 第二个队列和第三个队列都是按照时间排序,不同的是一个是读操作一个是写操作。

deadline IO 之所以区分读和写是因为设计者认为如果应用程序发了一个读请求,一般就会阻塞到那里,一直等到的结果返回。 而写请求则不是通常是应用请求写到内存即可,由后台进程再写回磁盘。应用程序一般不等写完成就继续往下走。 所以读请求应该比写请求有更高的优先级。

在这种设计下,每个新增请求都会先放到第一个队列,算法和Elevator的方式一样,同时也会增加到读或者写队列的尾端。这样首先处理一些第一队列的请求,同时检测第二/三队列前几个请求是否等了太长时间,如果已经超过一个阀值,就会去处理一下。 这个阀值对于读请求时 5ms, 对于写请求时5s.

个人认为对于记录数据库变更日志的分区,例如oracle 的online log, mysql 的binlog 等等,最好不要使用这种分区。 因为这类写请求通常是调用fsync 的。 如果写完不成,也会很影响应用性能的。

4、ANTICIPATORY

CFQ和DEADLINE考虑的焦点在于满足零散IO请求上。对于连续的IO请求,比如顺序读,并没有做优化。

为了满足随机IO和顺序IO混合的场景,Linux还支持ANTICIPATORY调度算法。ANTICIPATORY的在DEADLINE的基础上,为每个读IO都设置了6ms的等待时间窗口。如果在这6ms内OS收到了相邻位置的读IO请求,就可以立即满足。

小结

IO调度器算法的选择,既取决于硬件特征,也取决于应用场景。

在传统的SAS盘上,CFQ、DEADLINE、ANTICIPATORY都是不错的选择;对于专属的数据库服务器,DEADLINE的吞吐量和响应时间都表现良好。然而在新兴的固态硬盘比如SSD、Fusion IO上,最简单的NOOP反而可能是最好的算法,因为其他三个算法的优化是基于缩短寻道时间的,而固态硬盘没有所谓的寻道时间且IO响应时间非常短。

Linux·内核的 4 大 IO 调度算法文章来源地址https://www.toymoban.com/news/detail-405821.html

到了这里,关于Linux·内核的 4 大 IO 调度算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • linux性能优化-IO调度优化

    Linux I/O调度器(Linux I/O Scheduler)Linux内核中的一个组成部分,用户可以通过调整这个调度器来优化系统性能,介于通用块层和块设备驱动程序之间。 noop(No Operation) :通常用于内存存储的设备。 cfq(Completely Fair Scheduler ) :完全公平调度器,进程平均使用IO带宽。 deadline :针对

    2024年02月10日
    浏览(43)
  • 《深入Linux内核架构》第2章 进程管理和调度 (2)

    目录 2.4 进程管理相关的系统调用 2.4.1 进程复制 2.4.2 内核线程 2.4.3 启动新程序 2.4.4 退出进程 本专栏文章将有70篇左右,欢迎+关注,订阅后续文章。 1. _do_fork函数         fork vfork clone都最终调用_do_fork                 clone:通过CLONE_XX标志精确控制父子进程共享哪

    2024年04月11日
    浏览(27)
  • Linux内核分析(五)--IO机制原理与系统总线

    一、引言 二、I/O设备 ------2.1、块设备 ------2.2、字符设备 ------2.3、设备控制器 ------------2.3.1、I/O寻址 ------------2.3.2、内存映射 I/O 三、系统总线 ------3.1、数据总线 ------3.2、地址总线 ------3.3、控制总线 ------3.4、单总线结构 ------3.5、多总线结构 ------3.6、添加cache的三总线结构

    2024年02月05日
    浏览(38)
  • 【linux 多线程并发】多任务调度器,调度策略时间片轮转,先进先出,多种实时任务的策略,内核级最高优先级调度策略

    ​ 专栏内容 : 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。 手写数据库toadb 本专栏主要介绍如何从零开发,开发的

    2024年02月03日
    浏览(44)
  • 文件IO_文件读写(附Linux-5.15.10内核源码分析)

    目录 1.什么是文件偏移量? 1.1 文件偏移量介绍 1.2 文件偏移量重点 1.3 文件偏移量工作原理 2.文件偏移量设置 2.1 lseek函数 2.2 lseek内核源码分析 3.写文件 3.1 write函数 3.2 write内核源码分析 4.读文件 4.1 read函数 4.2 read内核源码分析 5.文件读写,文件偏移量设置示例代码 在介绍文

    2024年02月16日
    浏览(46)
  • 频繁设置CGroup触发linux内核bug导致CGroup running task不调度

    1. 说明 1 本篇是实际工作中linux上碰到的一个问题,一个使用了CGroup的进程处于R状态但不执行,也不退出,还不能kill,经过深入挖掘才发现是Cgroup的内核bug 2发现该bug后,去年给RedHat提交过漏洞,但可惜并未通过,不知道为什么,这里就发我博客公开了 3 前面的2个帖子《极简

    2023年04月15日
    浏览(49)
  • 【Linux】进程周边004之进程的调度与切换(领略Linux系统进程调度算法的神奇)

      👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.进程切换 2.进程调度 2.1Linux系统的进程调度算法如何实现兼顾进程优先级的设计

    2024年02月04日
    浏览(25)
  • Spark的内核调度

    目录 概述 RDD的依赖  DAG和Stage  DAG执行流程图形成和Stage划分  Stage内部流程 Spark Shuffle Spark中shuffle的发展历程 优化前的Hash shuffle  经过优化后的Hash shuffle  Sort shuffle Sort shuffle的普通机制 Job调度流程 Spark RDD并行度 Spark内核调度任务: 1.构建DAG有向无环图 2.划分stage夹断 3.Dri

    2024年01月17日
    浏览(31)
  • 深入讲解Linux内核中常用的数据结构和算法

    Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树。 Linux内核代码大量使用了链表这种数据结构。链表是在解决数组不能动态扩展这个缺陷而产生的一种数据结构。链表所包含的元素可以动态创建并插入和删除。链表的每个元素都是离散存放的,

    2023年04月16日
    浏览(28)
  • 【spark】spark内核调度(重点理解)

    Spark的核心是根据RDD来实现的,Spark Scheduler则为Spark核心实现的重要一环,其作用就是任务调度。Spark的任务调度就是如何组织任务去处理RDD中每个分区的数据,根据RDD的依赖关系构建DAG,基于DAG划分Stage,将每个Stage中的任务发到指定节点运行。基于Spark的任务调度原理,可以合

    2024年02月03日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包