磁盘调度与IO调度

背景

在一次数据库部署中,听到同事说修改磁盘调度算法为deadline,我诧异了,当时学习存储的时候磁盘调度算法没有这一项呃,翻了一些文档规范,也说deadline是磁盘调度算法。马上百度了一下deadline,原来是IO调度算法。本文从IO角度介绍磁盘调度和IO调度的区别与联系。

IO的概念

IO这个概念,充分理解就是输入输出。我们知道从最上层到最下层,层次之间存在着太多的接口,这些接口之间每次交互都可以称作一次IO,也就是广义上的IO。比如卷管理程序对磁盘控制器驱动程序API所做的IO,一次这种IO可能要产生针对磁盘的N个IO,也就是说上层的IO是稀疏的、简单的,越往下层走越密集、越复杂。

除了卷管理程序外,凌驾于卷管理之上的文件系统对卷的N个IO,就比卷更稀疏简单了。同样,上层应用对文件系统API的IO更加简单,只需要几句代码、几个调用就可以了。比如open()某个文件,seek()到某个位置,write()一段数据,close()这个文件等,就是一次IO。而就是这一次IO,可能对应文件系统到卷的N个IO,对应卷到控制器驱动的NXN个IO,对应控制器对最终磁盘的 N X N X N个IO。总之,磁盘一次IO就是磁头的一次连续读或写。而一次连续读或者写的过程,不管读写了几个扇区,扇区剩余部分均不能再使用。这无疑是比较浪费的,但是没有办法,总得有个最小单位。

以windows系统的IO简化流程图为例。

 图中的IO Manager是操作系统内核的一个模块,专门用来管理IO,并协调文件系统、卷、磁盘驱动程序各个模块之间的运作。整个流程解释如下。

某时刻,某应用程序调用文件系统接口,准备写入某文件从某个字节开始的若干字节。

  • IO Manager最初将这个请求发送给文件系统模块。

  • 文件系统将某个文件对应的逻辑便宜映射成卷的LBA地址偏移。

  • 文件系统向IO Manager请求调用卷管理软件模块的接口。

  • 卷管理软件将卷对应的LBA地址偏移翻译映射成实际物理磁盘对应的LBA地址偏移,并请求调用磁盘控制器驱动程序。

  • IO Manager向磁盘控制器驱动程序请求将对应的LBA地址段的数据从内存写入某块物理磁盘。

磁盘调度

概念

磁盘调度是在多道程序设计的计算机系统中,各个进程可能会不断提出不同的对磁盘进行读/写操作的请求。由于有时候这些进程的发送请求的速度比磁盘响应的还要快,因此我们有必要为每个磁盘设备建立一个等待队列。影响磁盘性能的首要因素是寻道速度,所以磁头处理等待队列的IO顺序使得全局用时最少至关重要,这个过程由磁盘调度算法决定,由磁盘控制器执行。

磁头扫描方式

假设目前磁盘控制器的队列中存在如下一些IO,这些IO所需要查找的磁道号码按照先后排列顺序为98,183,37,122,14,124,65,67,而当前磁头处于53号磁道,磁头执行寻道有以下几种模式。

FCFS(First Come First Serve)

磁头完全按照IO进入的先后顺序执行寻道操作,即从53号磁道跳到98号,然后到183号,再回到37号,依此类推。可以算出这个例子中此模式下磁头划过的磁道总数是640.如图所示。显然,FCFS模式不科学,在随机IO的环境中严重影响IO效率。

SSTF(Shortest Seek Time First)

此模式下,控制器会优先让磁头跳到离当前磁头位置最近的一个IO磁道去读写,读写完毕后,再次跳到离刚读写完这个磁道最近的一个IO磁道去读写,依此类推。SSTF模式下呈现的扫描图如图所示。

本例中磁头初始位置在53号磁道,如果此时IO队列中不断有位于53号磁道周围的磁道IO进入,比如55号、50号、51号磁道等,那么诸如183号这种离53号磁道较远的IO将会被饿死,永远也轮不到183号磁道的IO.所以SSTF模式是有很大限制的。

SCAN(回旋扫描模式)

这种扫描方式是最传统、最经典的方式了。它类似于电梯模型,从一端到另一端,然后折返,再折返,这样循环下去。磁头从最内侧磁道依次向外圈磁道寻道。然后项第题一样,如果这一层没有人等待搭乘,那么磁头就不在本层停止。也就是说如果当前队列中没有某个磁道的IO在等待,那么磁头就不会跳到这个磁道上,而是直接略过去,但是 SCAN 模型中,即使最外圈或者最内圈的磁道没有IO,磁头也要触及到才能折返,这就像50米往返跑一样,必须触及到终点线才能折返回去。

SCAN模式不会饿死任何IO,每个IO都有机会搭乘磁头这个电梯。然而,SCAN模式也会带来不必要的开销,因为磁头从来不会在中途折返,只能触及到终点之后才能折返。如果磁头正从中间磁道向外圈移动,而此时队列中进入一个内圈磁道的IO,那么此时磁道不会折返,即使队列中只有这一个IO。这个IO只能等待磁头初级最外圈之后折返回来被执行。

C-SCAN(单向扫描模式)

在C-SCAN模式中磁头总是从内圈向外圈扫描,达到外圈之后迅速返回内圈,返回途中不接受任何IO,然后再从内圈向外圈扫描。

LOOK(智能监察扫描模式)和C-LOOK(智能监察单向扫描模式)

LOOK模式相对于SCAN模式的区别在于,磁头不必达到终点之后才折返,而只要完成最两端的IO即可折返。同样,C-LOOK也是一样的道理,只不过是单向扫描。

 关于几种扫描模式的选择:总地说来,在负载不高的情况下,SSTF模式可以获得最佳的性能。但是鉴于可能造成某些较远的IO饿死地问题,所以在高负载条件下,SCAN或者C-SCAN、C-LOOK模式更为合适。

在大量随机IO的情况下,磁盘的磁头臂会像蜜蜂翅膀一样振动,当然他们的频率可能相差很大,但是用肉眼观察的话,磁头臂确实会像琴弦一样摆动,频率是比较高的。

IO调度

概念

I/O 调度是计算机操作系统用来决定将I/O操作提交到存储卷的顺序的方法。I/O 调度有时也称为磁盘调度。

内核中实现的IO调度器主要有四种--Noop, Anticipatory,CFQ, Deadline 。

IO调度算法

Noop算法

在Linux2.4或更早的版本的调度程序,那时只有这一种I/O调度算法。Noop调度算法也叫电梯调度算法,他将IO请求放入到一个FIFO队列中,然后逐个执行这些IO请求,当然对于一些在磁盘上连续的IO请求,Noop算法会适当做一些合并。这个调度算法特别适合不希望调度器重新组织IO请求顺序的应用。

这种调度算法在以下场景中优势比较明显:

  1. 在IO调度器下方有更加智能的IO调度设备。如果您的Block Device Drivers 是Raid,或者 SAN,NAS等存储设备,这些设备会更好地组织IO请求,不用IO调度器去做额外的调度工作;

  2. 上层的应用程序比IO调度器更懂底层设备。或者说上层应用程序到达IO调度器的IO请求已经是它精心优化的了,那么IO调度器不需要再画蛇添足,只需要按序执行上层传达下来的IO请求即可。

  3. 对于一些非旋转磁头式的存储设备,使用Noop效果会更好。因为对于旋转磁头式的磁盘来说,IO调度器的请求重组要花费一定的CPU时间,但是对于SSD磁盘来说,重组IO请求的时间可以节省下来,因为SSD提供了更智能的请求调度算法,不需要内核去画蛇添足。

Anticipatory算法

Anticipatory IO Scheduler (as scheduler)是老 2.6 内核中的默认调度程序——如果您没有指定一个,这就是将要加载的调度程序。 它实现了请求合并、单向电梯、读取和写入请求批处理,如果它认为用户要请求更多数据,它会在读取批处理后稍作延迟来尝试进行一些反攻击性读取。 它试图通过尽可能避免磁头移动来优化物理磁盘——这样做的一个缺点是它可能会在数据库或存储系统上提供高度不稳定的性能。

Anticipatory算法的核心是局部性原理,它期望一个进程昨晚一次IO请求后还会继续在此处做IO请求。在IO操作中,有一种现象叫“假空闲”(Deceptive idleness),它的意思是一个进程在刚刚做完一波读操作后,看似是空闲了,不读了,但是实际上它是在处理这些数据,处理完这些数据之后,它还会接着读,这个时候如果IO调度器去处理另外一个进程的请求,那么当原来的假空闲进程的下一个请求来的时候,磁头又得seek到刚才的位置,这样大大增加了寻道时间和磁头旋转时间。所以,Anticipatory算法会在一个读请求做完后,再等待一定时间t(通常是6ms),如果6ms内,这个进程上还有读请求过来,那么我继续服务,否则,处理下一个进程的读写请求。

在一些场景下,Anticipatory算法对于随机读取会造成比较大的延时,对数据库应用很糟糕,而对于 Web Server 等则会表现的不错。这个算法也可以简单理解为面向低速磁盘的,因为那个”猜测”实际上的目的是为了减少磁头移动时间。

Anticipatory算法从Linux 2.6.33版本后,就被移出了,因为配置CFQ也能达到Anticipatory算法的效果。

CFQ算法

CFQ(Completely Fair Queuing,绝对公平算法) 的特点是按照IO请求的地址进行排序,而不是按照先来后到的顺序进行响应。在传统的SAS盘上,磁盘寻道花去了绝大多数的IO响应时间。CFQ的出发点是对IO地址进行排序,以尽量减少磁盘旋转次数来满足尽可能多的IO请求。在CFQ算法下,SAS盘的吞吐量大大提高了。但是相比于NOOP的缺点是:先来的IO请求并不一定能被满足,可能会出现饿死的情况。 CFQ对每个进程维护一个 IO 队列,各个进程发来的 IO 请求会被 cfq 以轮循方式处理。也就是对每一个 IO 请求都是公平的。这使得 cfq 很适合离散读的应用(eg: OLTP DB)。

从Linux 2.6.18起,CFQ作为默认的IO调度算法。

对于通用的服务器来说,CFQ是较好的选择。

CFQ 排序和磁盘调度算法中的C-LOOK顺序是一样的。

Deadline算法

deadline 算法实现请求合并,单向电梯,并为所有操作施加期限以防止饿死,这和磁盘调度算法中 C-SCAN 逻辑是一样的,某种意义上说,Deadline是 C-SCAN 的扩展。 因为在 linux 中写入会立即返回,实际数据保存在缓存中,所以deadline调度程序也将优先选择读取——只要写入请求的还没有过期。 内核文档建议这是数据库系统的首选调度程序,特别是有感知磁盘或任何具有高磁盘性能的系统。

DEADLINE在CFQ的基础上,解决了IO请求饿死的极端情况。除了CFQ本身具有的IO排序队列之外,DEADLINE额外分别为读IO和写IO提供了FIFO队列。读FIFO队列的最大等待时间为500ms,写FIFO队列的最大等待时间为5s。FIFO队列内的IO请求优先级要比CFQ队列中的高,,而读FIFO队列的优先级又比写FIFO队列的优先级高。

优先级可以表示如下: FIFO(Read) > FIFO(Write) > CFQ

对SSD和普通机械硬盘来说,调度算法完全是两种不同的策略。SSD算法需要解决的是单个数据位有效擦写次数问题,保证数据存储安全稳定,而机械硬盘更关注的是读写速度问题。二者可以说是完全不一样的东西。

IO调度和磁盘调度的区别与联系

1. 从某种意义上说,磁盘调度指的磁盘IO也是一种IO,只不过是硬件层IO;而IO调度的IO则指的是操作系统软件层IO。
2. 提高磁盘效率是早期磁盘调度算法的主要焦点,由于现代硬盘驱动器隐藏了它们的内部细节并且只暴露了有限的逻辑块号 (LBN) 接口,这些算法必须在磁盘控制器的固件中实现,且只有驱动器供应商才能实现。
3. IO调度方法将详细的设备特性带到上层,以便操作系统可以执行更好的调度。IO调度程序通过使用基于 LBN 的近似寻道减少算法来优化磁盘性能,也有的基于有关磁盘 I/O 延迟的准确信息来重排序。 Linux 是 I/O 调度器方面最丰富的操作系统,所有这些调度程序都依赖于常规的 LBN 接口 。

参考资料

I/O scheduling

磁盘调度算法

磁盘调度策略

Linux I/O 调度器

Efficient I/O Scheduling with Accurately Estimated Disk Drive Latencies

大话存储终极版

更多技术文章参看达梦社区:http://eco.dameng.com

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值