linux的每次IO大小控制,Linux IO磁盘篇整理小记

起源

本篇起源于对Kafka的一个问题排查,大体的缘由是达到磁盘性能瓶颈。在追踪问题的时候用到iostat -x这命令,详细示例以下:

linux的每次IO大小控制,Linux IO磁盘篇整理小记_第1张图片ios

能够看到%idle(%idle小于70%说明IO压力已经比较大了)和%util的值都处于非正常状态。不过这里并不讲述Kafka的问题排查过程,反而是来说述下IO指标的一些知识。每次遇到须要查看磁盘相关信息的时候,一些指标都会或多或少的遗忘,还要翻阅各类资料了解,故这里对相关的信息作一个相关的整理,在巩固相关知识点的同时也方便之后的查阅。算法

上面示例中的各个指标的含义分别为:

avg-cpu说明:

%user:在用户级别运行所使用的CPU的百分比。

%nice:带nice值(和进程优先级相关)的用户模式下运行所使用的CPU的百分比。

%system:在系统级别运行所使用CPU的百分比。

%iowait:CPU等待IO完成的时间百分比。(单个iowait指标值偏高并不能说明磁盘存在IO瓶颈,下面会有详述。)

%steal:管理程序维护另外一个虚拟处理器时,虚拟CPU的无心识等待时间的百分比。

%idle:CPU空闲时间的百分比。(idle值高,表示CPU较空闲。)

device说明:

rrqm/s:每秒进行merge的读操做数目。即:rmerge/s

wrqm/s:每秒进行merge的写操做数目。即:wmerge/s

r/s:每秒完成的读IO设备的次数。即rio/s

w/s:每秒完成的写IO设备的次数。即wio/s

rsec/s:每秒读扇区数。即rsect/s(每一个扇区大小为512B。)

wsec/s:每秒写扇区数。即wsect/s

avgrq-sz:平均每次设备IO操做的数据大小(扇区);平均单次IO大小。

avgqu-sz:平均IO队列长度。

await:从请求磁盘操做到系统完成处理,每次请求的平均消耗时间,包括请求队列等待时间;平均IO响应时间(毫秒)。

svctm:平均每次设备IO操做的服务时间(毫秒)。

%util:一秒中有百分之多少的时间用于 I/O 操做,即被io消耗的cpu百分比。缓存

正常状况下svctm应该是小于await值的,而svctm的大小和磁盘性能有关,CPU、内存的负荷也会对svctm值形成影响,过多的请求也会间接的致使svctm值的增长。await值的大小通常取决于svctm的值和IO队列的长度以及IO请求模式,若是scvtm比较接近await,说明IO几乎没有等待时间;若是await远大于svctm,说明IO请求队列太长,IO响应太慢,则须要进行必要优化。

若是%util接近100%,说明产生的IO请求太多,IO系统已经满负荷,该磁盘可能存在瓶颈。

队列长度(avgqu-sz)也可做为衡量系统 I/O 负荷的指标,但因为 avgqu-sz 是按照单位时间的平均值,因此不能反映瞬间的 I/O 泛洪,若是avgqu-sz比较大,则说明有大量IO在等待。

(能够看完下面一节再来回顾这段内容。)服务器

相关原理

对于await, svctm以及%util等,光从概念上来讲,比较晦涩,能够经过下图的磁盘IO流程来加深理解:

linux的每次IO大小控制,Linux IO磁盘篇整理小记_第2张图片微信

(此图来源于遗产流....从新画了一遍)markdown

磁盘IO场景网络

用户调用标准C库进行IO操做,数据流为:应用程序buffer->C库标准IObuffer->文件系统page cache->经过具体文件系统到磁盘。

用户调用文件IO,数据流为:应用程序buffer->文件系统page cache->经过具体文件系统到磁盘。

用户打开文件时使用O_DIRECT,绕过page cache直接读写磁盘。

用户使用相似dd工具,并使用direct参数,绕过系统cache与文件系统直接写磁盘。

发起IO请求请的步骤简析(以最长链路为例)

写操做:并发

用户调用fwrite把数据写C库标准IObuffer后就返回,即写操做一般是个异步操做。

数据到C库标准IObuffer后,不会当即刷新到磁盘,会将屡次小数据量相邻写操做先缓存起来合并,最终调用write函数一次性写入(或者将大块数据分解屡次write调用)page cache。

数据到page cache后也不会当即刷新到磁盘,内核有pdflush线程在不停的检测脏页,判断是否要写回到磁盘中,若是是则发起磁盘IO请求。

读操做:

用户调用fread到C库标准IObuffer读取数据,若是成功则返回,不然继续。

到page cache读取数据,若是成功则返回,不然继续。

发起IO请求,读取到数据后缓存buffer和C库标准IObuffer并返回。能够看出,读操做是同步请求。

IO请求处理异步

通用块层根据IO请求构造一个或多个bio结构并提交给调度层。bio结构描述对一个磁盘扇区读/写操做。

调度器将bio结构进行排序和合并组织成队列且确保读写操做尽量理想:将一个或多个进程的读操做合并到一块儿读,将一个或多个进程的写操做合并到一块儿写,尽量变随机为顺序(由于随机读写比顺序读写要慢),读必须优先知足,而写也不能等过久。

IO调度算法

Linux的IO调度器有时也称之为磁盘调度器,工做机制是控制块设备的请求队列,肯定队列中那些IO的优先级更高以及什么时候下发IO到块设备,以此来减小磁盘寻到时间,从而提升系统的吞吐量。

目前Linux共有以下几种IO调度算法:函数

NOOP

NOOP算法的全写为No Operation。该算法实现了最最简单的FIFO队列,全部IO请求大体按照先来后到的顺序进行操做。之因此说“大体”,缘由是NOOP在FIFO的基础上还作了相邻IO请求的合并,并非完彻底全按照先进先出的规则知足IO请求。

假设有以下的io请求序列:

100,500,101,10,56,1000

NOOP将会按照以下顺序知足:

100(101),500,10,56,1000

二、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请求并不必定能被知足,可能会出现饿死的状况。

三、DEADLINE

DEADLINE在CFQ的基础上,解决了IO请求饿死的极端状况。除了CFQ自己具备的IO排序队列以外,DEADLINE额外分别为读IO和写IO提供了FIFO队列。读FIFO队列的最大等待时间为500ms,写FIFO队列的最大等待时间为5s。FIFO队列内的IO请求优先级要比CFQ队列中的高,而读FIFO队列的优先级又比写FIFO队列的优先级高。优先级能够表示以下:

FIFO(Read) > FIFO(Write) > CFQ

四、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/scheduler

noop 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混淆起来。顾名思义,就是系统由于io致使的进程wait。再深一点讲就是:这时候系统在作IO,致使没有进程在干活,cpu在执行idle进程空转,因此说iowait的产生要知足两个条件,一是进程在等IO,二是等IO时没有进程可运行。

经常使用的top命令中也有iowait的指标展现(%wa就是%iowait),示例以下:

linux的每次IO大小控制,Linux IO磁盘篇整理小记_第3张图片

对 iowait 常见的误解有两个:1. 误觉得 iowait 表示CPU不能工做的时间;2. 误觉得 iowait 表示I/O有瓶颈问题。iowait 的首要条件就是CPU空闲,既然空闲固然就能够接受运行任务,只是由于没有进程能够运行,CPU才进入空闲状态的。那为何没有进程能够运行呢?由于进程都处于休眠状态、在等待某个特定事件:好比等待定时器、或者来自网络的数据、或者键盘输入、或者等待I/O操做完成,等等。iowait的升高并不能证实等待IO进程的数量增多了,也不能证实等待IO的总时间增长了。例如,在CPU繁忙期间发生的I/O,不管IO是多仍是少,iowait都不会变;当CPU繁忙程度降低时,有一部分IO落入CPU空闲时间段内,致使iowait升高。再好比,IO的并发度低,iowait就高;IO的并发度高,iowait可能就比较低。因此iowait 所含的信息量很是少,它是一个很是模糊的指标,若是看到 iowait 升高,还需检查I/O量有没有明显增长,相应的一些指标有没有明显增大,应用有没有感受变慢,若是都没有,就没什么好担忧的。

Plus: 可使用iotop命令来查找引发高iowait对应的进程。查看CPU使用率及负载的一些命令有:top、vmstat、mpstat、uptime等。

PS:消息中间件(Kafka、RabbitMQ)交流可加微信:hiddenzzh

欢迎支持笔者新书:《RabbitMQ实战指南》以及关注微信公众号:Kafka技术专栏。

你可能感兴趣的:(linux的每次IO大小控制)