声明,本文章内容大量拷贝自原文:,本文章只是对该文章的部分内容的摘选,如果您想更深入仔细的了解IO调度算法,推荐您直接阅读原文:)
之前蘑菇街电话面试的时候面试官问我IO调度算法有哪些,之前没留意过这个东西,记录一下:)
对于普通的机械硬盘,我们完成一次IO读写的流程从硬盘的物理结构上来说是,机械硬盘的存储介质是磁盘,磁头在盘片上移动进行磁道寻址,行为类似播放一张唱片。这种结构的特点是,顺序访问时吞吐量较高,但是如果一旦对盘片有随机访问,那么大量的时间都会浪费在磁头的移动上,这时候就会导致每次IO的响应时间变长,极大的降低IO的响应速度。磁头在盘片上寻道的操作,类似电梯调度,如果在寻道的过程中,能把顺序路过的相关磁道的数据请求都“顺便”处理掉,那么就可以在比较小影响响应速度的前提下,提高整体IO的吞吐量。这就是我们问什么要设计IO调度算法的原因。
常见的算法总结:
CFQ完全公平队列(Completely Fair Queueing)
cfq就是试图给所有进程分配等同的块设备使用的时间片,进程在时间片内,可以将产生的IO请求提交给块设备进行处理,时间片结束,进程的请求将排进它自己的队列,等待下次调度的时候进行处理。这就是cfq的基本原理。
DeadLine最终期限调度
deadline调度算法相对cfq要简单很多。其设计目标是,在保证请求按照设备扇区的顺序进行访问的同时,兼顾其它请求不被饿死,要在一个最终期限前被调度到。我们知道磁头对磁盘的寻道是可以进行顺序访问和随机访问的,因为寻道延时时间的关系,顺序访问时IO的吞吐量更大,随机访问的吞吐量小。如果我们想为一个机械硬盘进行吞吐量优化的话,那么就可以让调度器按照尽量复合顺序访问的IO请求进行排序,之后请求以这样的顺序发送给硬盘,就可以使IO的吞吐量更大。但是这样做也有另一个问题,就是如果此时出现了一个请求,它要访问的磁道离目前磁头所在磁道很远,应用的请求又大量集中在目前磁道附近。导致大量请求一直会被合并和插队处理,而那个要访问比较远磁道的请求将因为一直不能被调度而饿死。deadline就是这样一种调度器,能在保证IO最大吞吐量的情况下,尽量使远端请求在一个期限内被调度而不被饿死的调度器。
Noop调度器
noop调度器是最简单的调度器。它本质上就是一个链表实现的fifo队列,并对请求进行简单的合并处理。调度器本身并没有提供任何可疑配置的参数。
各种调度器的应用场景选择
从原理上看,
cfq是一种比较通用的调度算法,它是一种以进程为出发点考虑的调度算法,保证大家尽量公平,为所有进程分配等量的带宽,适合于桌面多任务及多媒体应用。
deadline是一种以提高机械硬盘吞吐量为思考出发点的调度算法,尽量保证在有io请求达到最终期限的时候进行调度,非常适合业务比较单一并且IO压力比较重的业务,比如数据库。
而noop呢?其实如果我们把我们的思考对象拓展到固态硬盘,那么你就会发现,无论cfq还是deadline,都是针对机械硬盘的结构进行的队列算法调整,而这种调整对于固态硬盘来说,完全没有意义。对于固态硬盘来说,IO调度算法越复杂,额外要处理的逻辑就越多,效率就越低。所以,固态硬盘这种场景下使用noop是最好的,deadline次之,而cfq由于复杂度的原因,无疑效率最低。
如何(查看&&修改)我们OS上的IO调度算法?
查看当前系统支持的IO调度算法
[root@VM_58_172_centos ~]# dmesg | grep -i scheduler[ 0.580914] io scheduler noop registered[ 0.582382] io scheduler deadline registered (default)[ 0.584125] io scheduler cfq registered
查看某块硬盘的IO调度算法
[root@VM_58_172_centos ~]# cat /sys/block/vda/queue/schedulernone[root@VM_58_172_centos ~]# cat /sys/block/vdb/queue/schedulernone
修改某块硬盘的IO调度算法
[root@VM_58_172_centos ~]# echo cfq > /sys/block/vda/queue/scheduler[root@VM_58_172_centos ~]# cat /sys/block/vda/queue/schedulernone
我是在虚拟云主机上做的实验,不知为什么无法修改对应硬盘的IO调度算法,或许是供应商对此做了限制?之后再去细查一下。
参考:
Linux的IO调度(分析的很深入,严重推荐~):