现在 HDD 磁盘采用的调度算法有多种,常见的有以下几类:
- 完全公平队列(CFQ):适用于大多数通用场景。它试图为每个进程提供公平的磁盘访问机会,将 I/O 请求均匀地分布到各个进程中,能较好地满足多个进程同时对磁盘进行读写的需求,在桌面环境和一般服务器环境中都有广泛应用。
- 截止时间调度器(Deadline):适合 I/O 密集型应用,能减少延迟。它将读请求和写请求分开处理,读请求具有更高的优先级,同时为每个请求设置了一个截止时间,保证请求不会被无限期延迟,可有效避免 “饥饿” 现象,提高系统的响应速度,常用于数据库服务器等对 I/O 响应要求较高的场景。
- 无操作调度器(NOOP):适用于低负载系统,能减少 CPU 开销。该算法将 I/O 请求放入一个 FIFO 队列中,逐个执行,对于磁盘上连续的 IO 请求会进行合并,在一些特殊场景如底层存储设备本身具有强大的调度能力,或者上层应用已经对 I/O 请求进行了充分优化的情况下使用。
- 预算公平队列(BFQ):主要用于优化 I/O 性能,适合随机读写密集型应用。它会为每个进程分配一个预算,根据进程的 I/O 需求和预算来调度请求,以实现更公平和高效的磁盘访问,能有效提高随机读写的性能,在一些对随机读写性能要求较高的场景如多媒体应用、桌面环境中的文件系统等表现较好。
通用的经典算法
- 先来先服务(FCFS):按照请求到达的顺序进行处理,简单、公平,但效率不高,相邻请求的磁道可能相隔较远,导致磁头移动距离长,平均寻道时间长,适用于磁盘 I/O 请求较少且请求访问的磁道比较集中的情况。
- 最短寻道时间优先(SSTF):每次选择离当前磁头位置最近的未服务请求进行服务,可减少寻道时间,但可能导致某些请求长时间得不到服务,产生 “饥饿” 现象,适用于磁盘 I/O 请求较为频繁且分布不均的场景。
- 扫描算法(SCAN):又称电梯算法,磁头从一端开始向另一端移动,期间依次服务沿途的所有请求,到达磁盘边界后立即返回,沿相反方向继续服务剩余请求,可减少平均寻道时间,确保所有磁道都能被访问到,但可能导致某些磁道的访问延迟较长,常用于处理大量磁盘 I/O 请求的场景。
- 循环扫描算法(C-SCAN):是 SCAN 算法的改进,磁头仅在一个移动方向上提供访问服务,返回时直接快速移至起始端,不服务任何请求,使各个位置磁道的响应频率更均匀,但实现相对复杂。
linux系统,检查磁盘调度算法命令
- hdd磁盘一般是 deadline算法。
- nvme一般是none,因为不需要旋转和磁头臂移动。
查询方法:
- 1.通过cat命令查看/sys/block目录下的调度算法文件
/sys/block目录包含了系统中所有块设备的信息,每个磁盘设备都有一个对应的子目录,在这些子目录下有一个名为queue/scheduler的文件,该文件记录了磁盘当前使用的调度算法。
如下面所示:
# lsblk获取所有磁盘信息
lsblk | grep -vE 'part|rbd|lvm|mpath|raid'
# 查看磁盘sda的调度器信息
$ cat /sys/block/sda/queue/scheduler
noop [deadline] cfq
# 查看SSD nvme0n1的调度器信息
$ cat /sys/block/nvme0n1/queue/scheduler
[none] mq-deadline kyber
上面中括号[]
内的调度算法即为当前磁盘正在使用的调度算法,在这个例子中,sda磁盘使用的是mq-deadline
调度算法。nvme0磁盘使用的是none
调度算法。
-
- 使用udevadm命令查看
udevadm
是一个用于管理udev设备管理器的命令行工具,你可以通过它来获取设备的属性信息,包括磁盘的调度算法。
- 使用udevadm命令查看
# udevadm 可以查询磁盘的信息,然后用管道符查询 grep ID_SCSI_SCAN_SCHEDULER,根据不同的版本查询到的内容不同。建议用上面的命令查询更准确。
$ udevadm info --query=property --name=sda
该命令会输出与磁盘调度算法相关的属性信息,如果存在则可以从中获取到调度算法的名称。不过这种方法在不同的系统和内核版本中可能并不一定能准确获取到所需信息,主要还是推荐使用第一种方法。