Linux IO磁盘篇整理小记( 二 )


IO请求处理
1. 通用块层根据IO请求构造一个或多个bio结构并提交给调度层 。bio结构描述对一个磁盘扇区读/写操作 。
2. 调度器将bio结构进行排序和合并组织成队列且确保读写操作尽可能理想:将一个或多个进程的读操作合并到一起读,将一个或多个进程的写操作合并到一起写,尽可能变随机为顺序(因为随机读写比顺序读写要慢),读必须优先满足,而写也不能等太久 。
IO调度算法
linux的IO调度器有时也称之为磁盘调度器,工作机制是控制块设备的请求队列,确定队列中那些IO的优先级更高以及何时下发IO到块设备,以此来减少磁盘寻到时间,从而提高系统的吞吐量 。目前Linux共有如下几种IO调度算法:
1. NOOP
NOOP算法的全写为No Operation 。该算法实现了最最简单的FIFO队列,所有IO请求大致按照先来后到的顺序进行操作 。之所以说“大致”,原因是NOOP在FIFO的基础上还做了相邻IO请求的合并,并不是完完全全按照先进先出的规则满足IO请求 。
假设有如下的io请求序列:
100,500,101,10,56,1000
NOOP将会按照如下顺序满足:
100(101),500,10,56,1000
2、CFQ
CFQ算法的全写为Completely Fair Queuing 。该算法的特点是按照IO请求的地址进行排序,而不是按照先来后到的顺序来进行响应 。
假设有如下的io请求序列:
100,500,101,10,56,1000
CFQ将会按照如下顺序满足:
100,101,500,1000,10,56
CFQ是默认的磁盘调度算法,对于通用服务器来说最好的选择 。它视图均匀地分布对IO带宽的访问 。CFQ为每个进程单独创建一个队列来管理该进程所产生的请求,也就是说每个进程一个队列,各队列之间的调度使用时间片来调度,以此来保证每个进程都能被很好的分配到IO带宽 。IO调度器每次执行一个进程的4次请求 。在传统的SAS盘上,磁盘寻道花去了绝大多数的IO响应时间 。CFQ的出发点是对IO地址进行排序,以尽量少的磁盘旋转次数来满足尽可能多的IO请求 。在CFQ算法下,SAS盘的吞吐量大大提高了 。但是相比于NOOP的缺点是,先来的IO请求并不一定能被满足,可能会出现饿死的情况 。
3、DEADLINE
DEADLINE在CFQ的基础上,解决了IO请求饿死的极端情况 。除了CFQ本身具有的IO排序队列之外,DEADLINE额外分别为读IO和写IO提供了FIFO队列 。读FIFO队列的最大等待时间为500ms,写FIFO队列的最大等待时间为5s 。FIFO队列内的IO请求优先级要比CFQ队列中的高,而读FIFO队列的优先级又比写FIFO队列的优先级高 。优先级可以表示如下:
FIFO(Read) > FIFO(Write) > CFQ
4、ANTICIPATORY
CFQ和DEADLINE考虑的焦点在于满足零散IO请求上 。对于连续的IO请求,比如顺序读,并没有做优化 。为了满足随机IO和顺序IO混合的场景,Linux还支持ANTICIPATORY调度算法 。ANTICIPATORY的在DEADLINE的基础上,为每个读IO都设置了6ms的等待时间窗口 。如果在这6ms内OS收到了相邻位置的读IO请求,就可以立即满足 。anticipatory 算法通过增加等待时间来获得更高的性能,假设一个块设备只有一个物理查找磁头(例如一个单独的SATA硬盘),将多个随机的小写入流合并成一个大写入流(相当于给随机读写变顺序读写),使用这个原理来使用读取写入的延时换取最大的读取写入吞吐量.适用于大多数环境,特别是读取写入较多的环境 。
不同的磁盘调度算法(以及相应的IO优化手段)对Kafka这类依赖磁盘运转的应用的影响很大,建议根据不同的业务需求来测试选择合适的磁盘调度算法(以后的文章中会有相关的测试介绍) 。
查看设备当前的IO调度器:cat /sys/block/{DEVICE-NAME}/queue/scheduler 。其中{DEVICE-NAME}指的是磁盘设备的名称,即文章开头iostat -x中Device下方的vda,vdb等 。
举例:
[root@hidden ~]# cat /sys/block/vda/queue/schedulernoop anticipatory deadline [cfq]修改当前的IO调度器: echo {SCHEDULER-NAME} > /sys/block/{DEVICE-NAME}/queue/scheduler 。其中{SCHEDULER-NAME}取值为noop、anticipatory、deadline、cfq其中之一 。
举例:
[root@hidden ~]# echo noop > /sys/block/vda/queue/scheduler [root@hidden ~]# cat /sys/block/vda/queue/scheduler[noop] anticipatory deadline cfq以上设置重启之后会失效,如果要想重启后配置仍然生效,需要在内核启动参数中将elevator={SCHEDULER-NAME}写入/boot/grub/menu.lst文件中 。在修改这个文件之前最好先备份一份,然后将elevator={SCHEDULER-NAME}添加到文件末尾即可 。
三、iowait
单独拎出iowait来说明是因为很多人对这个指标有一定的误区,包括笔者也经常把iowait和await混淆起来


推荐阅读