Linux I/O调度器备忘
前言
当程序写好了,需要对它的性能做一个压测,系统的瓶颈,简要来说可以分成
- CPU
- 磁盘 I/O
- 网络 I/O
(这里没有考虑分布式情况下的高可用等问题)
本文对于磁盘I/O方面,就Linux I/O调度器方面的知识做了点简单整理,作为备忘。
Linux I/O 系统简介
▲ 图片来源:IBM 《调整 Linux I/O 调度器优化系统性能》
预备知识-磁盘
机械硬盘(HDD)
机械硬盘以扇区为磁盘寻址的单位,读取数据时,需要先把磁臂移动到指定磁道,然后将扇区旋转到磁头下。
这里有个经典的调度算法就是电梯(SCAN)调度算法
固态硬盘(SSD)
固态用电压从晶体里储存读取数据,这方面来说,不会像HDD一样受到旋转速度的限制,不存在机械操作。
引用一个不准(tong)确(su)的例子
我给你举个特别不恰当的比方吧,因为我实在是想不出更恰当的了。
抗日战争片看过吧?摇把子电话见过吧?这种电话是没有拨号盘的,那怎么用呢?
首先你要摇电话上的把手,然后接线员会接你的电话,你跟接线员说我要接司令部,接线员就找到司令部的电话线接口,然后把你的电话线插!在!上!面!
这就相当于是机械寻址。
影响接线员速度的因素有:接线员手速(硬盘转速),接线员的数量(磁头数)。可以想象的是电话号码越多找目标电话号码越慢。因为需要一个一个找啊。
而你现在打电话只需要拨个号,程控交换机就会帮你接好线路。这个寻找目标电话号码的任务你就可以认为是电子寻址。这种电子寻址几乎不会因为号码空间的大小而产生明显的不同。
关于固态硬盘的寻址原理和寻址速度的一个疑问? - Zign的回答 - 知乎 https://www.zhihu.com/question/58752580/answer/159003701
可以通过以下命令区分HDD和SSD
1 | 通过lsblk 查看, ROTA意思为rotational device, 0为假,1为真 |
简单粗暴地来说,旋转的是机械硬盘,非旋转的是固态硬盘。
I/O调度器
下面以CentOS为例
1 | hostnamectl |
可以看到,现在可用的调度器有5个
NOOP
全称为No Operation,中文名称电梯调度器,I/O请求首先进入一个FIFO接受队列,然后合并后,从调度队列大致按照到达的先后依次进行操作,由于不需要对请求再次排序,这个调度方式和固态硬盘配合最好。
Deadline(默认使用)
中文名称为截止时间调度器,它会把请求划分成读操作和写操作,它将读写操作分开处理。使用了四个队列,两个分别按处理读写,按初始扇区排序,另外两个队列为读/写请求的,按最后截止时间排序的队列。默认情况下,读取请求的到期时间是500ms,而写入请求的到期时间是5s。它能避免有些请求长时间不被处理的情况。
CFQ
CFQ全称Completely Fair Scheduler(
这是怎么缩写的),中文名称完全公平调度器,它的主要目标是在所有进程间公平地分配I/O带宽,为此,会使用大量(默认值为64)已经排序的队列来分别存储来自不同进程的请求。I/O请求到达时,通过哈希函数对PID求值放入到相应标识的队列末尾,因此同一进程的请求总是会在同一队列中被依次处理。MQ-Deadline
适用于多线程版本的Deadline调度器, 该调度程序适用于大多数用例,但特别是那些读操作比写操作更频繁发生的用例。
Kyber
Kyber适用于快速多队列任务,它把I/O请求分为两个队列,一个用于同步请求,一个用于异步请求。它通过限制发送到调度队列的I/O操作,确保较高优先级的请求能快速被完成,可以通过设置延迟来调整等待时间,默认读操作是2ms,写操作是10ms,把这两个值调小,可以保证较低的延迟,但也会由于缺少合并,而影响到吞吐量。这方面资料很少,有兴趣的猛士可以看下源码。
对于不同的场景下,RedHat有提供参考的配置
Use case | Disk scheduler recommendation |
---|---|
Traditional HDD with a SCSI interface | Use mq-deadline or bfq . |
High-performance SSD or a CPU-bound system with fast storage | Use none , especially when running enterprise applications. Alternatively, use kyber . |
Desktop or interactive tasks | Use bfq . |
Virtual guest | Use mq-deadline . With a multi-queue host bus adapter (HBA), use none . |
渣翻下
使用场景 | 推荐的磁盘调度方式 |
---|---|
机械硬盘 | mq-deadline |
固态硬盘 | CPU绑定的快速存储设备 | none |
PC程序 | 交互任务 | bfq |
虚拟化 | mq-deadline , 如果有FC HBA卡,用none |
具体的配置需要根据自己程序的读写特点分别测试,这个表只是个参考。
调度器的配置与切换
I/O调度器的选择
不同版本启用的默认调度器不同,主要分为两类
支持多队列的:mq-deadline
, kyber
, noop
不支持多队列的:noop
, cfq
, deadline
这两类配置无法同时启用
同类配置中,I/O调度器的切换不需要重启机器
1 | 修改I/O调度器 |
假如要切换到多队列调度器,操作稍微复杂点
1 | 修改grub配置文件 |
在配置项GRUB_CMDLINE_LINUX
的引号内,末尾添加scsi_mod.use_blk_mq=1
添加完成后,需要重新生成grub2.cfg
不同的设备类型,接下来输出的配置文件目录也不同,可以通过如下命令来确认设备类型
1 | test -d /sys/firmware/efi && echo "UEFI" || echo "Legacy" |
以Legacy
设备为例(UEFI
的配置可参见此处)
1 | grub2-mkconfig -o /boot/grub2/grub.cfg |
设置完成后,重启机器即可生效
1 | sudo reboot |
参考资料
- 1.2022年,这篇文章的链接地址已经失效 ↩
版权声明:
除另有声明外,本博客文章均采用 知识共享(Creative Commons) 署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议 进行许可。
分享