I/O scheduler的作用就是为请求队列里面的IO请求做一个优化,以此达到提高系统吞吐量、缩短响应时间的目的。更改I/O scheduler有两种方式:
1./sys/block/device_name/queue/scheduler(IOscheduler);/sys/block/device_name/queue/nr_request(queue
size)
2.永久修改?启动时,grup->edit->elevator
= scheduler_name
但是提高系统吞吐量和缩短响应时间是一件矛盾的事情。因为如果为了提高系统吞吐量,则必然要对IO请求的某些顺序做改变,这就导致了某些IO请求的响应时间增大。而如果为了减小响应时间(那么就是来一个请求响应一个)那么系统吞吐量或许就会降低了。因此linux有了四种I/O scheduler来满足不同的情况。
1.
CFQ(completely fair queuing)
完全公平队列,实现了请求合并、电梯算法。每个进程的IO请求产生一个队列,这个队列是对寻道地址进行排序,尽量减少寻道时间。每个进程的队列有自己的优先级,然后以时间片轮转的方式去服务每个进程的请求队列。[1]
2.
Deadline
这种调度方式实现了请求合并、电梯算法,然后为每个请求分配一个超期时间,这样就避免了某个请求被饿死的情况。在它的实现中分配了好几个队列,deadline queue(这个是根据超期时间来排序的),这个是按照磁道访问顺序来的;write queue;read queue。其中read queue的优先级比write queue的优先级高,这主要是因为用户发出了读请求后会立马等待结果,而用户发出了写请求后则不会等待他是否完成了(因为用户看不到)。这三者的优先级关系是Q(read) > Q(read) > Q(deadline)。大概的响应流程:决定下一次是从队列中响应哪个请求时,首先是从Q(deadline)去查看第一个请求是否超期了,如果没有那么就会从read或write队列(这个应该是根据他们之间的优先级来定的)里面读取一批的请求去响应(默认好像是5个)。
3.
NOOP
NOOP的全称是no operations,它就是一个简单的FIFO,不过它实现了合并请求的功能,也就是说如果两个请求访问的额磁道地址在一起,那么就会合并它们。这种适用于没有寻到时间的情况,比如说SSD、fusion IO,而不适应HDD。
4.
AS
AS其实和CFQ差不蛮多,称作预期的调度,别的IO scheduler都只是对离散IO做了优化但是并没有对连续IO作优化,比如说一个IO请求刚执行完的这瞬间又在此位置来了一个IO请求,那么在AS这种情况下就可以马上响应刚才新来的那个请求,它是通过每次完成之后等那么极短的时间来响应的(6ms?)不过现在已经被CFQ取代。
简单的说:CFQ是一种通用方案,deadline适用database情景,而NOOP适用SSD、fusion IO。但是具体的也要看实际情况,比如说deadline只有在极大地IO情况下才有可能提升一定的性能(自己做过测试,规模比较小,没有多大性能提升)
下面在谈谈queue size
Queue size就是用来存在IO请求的队列的大小,所以理论上来说queue size越大,提升的性能更大,因为有更多的请求被优化了。但是这里需要注意几种情况。
1.
在SSD、Fusion IO这种不需要寻道时间(seek time)的情景下,增大了size并没有多大益处,或许会因为对队列的维护而带来负面影响。所以使用之前最好还是测试一下比较合适。
2.
在使用innodb的时候,无论是CFQ还是deadline,都不要设置为太大的queue size。因为有人说(不是官方说法[2])innodb内部也对io请求做了根os一样的优化,那么如果在os层把queue size设得太大的话会与innodb内部重复,导致额外的代价,性能或许会更低。
3.
Linux的文档中说deadline比CFQ更适合数据库这种情况,但是貌似只有在极大地系统压力情况下deadline才会比CFQ有比较大的性能优势。
介绍了cfq/deadline的一些细节。
没有评论:
发表评论