影响因素:
生产者和消费者队列速率:实质是生产者消费者队列优化,保证CPU的持续占用率;
磁盘IO速率:ETL会有文件的抽取、解析和读写,这个过程里面涉及大批量的磁盘读写操作,这也是最容易造成性能瓶颈的地方。
经过测试发现
iostat -x 2
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 1.60 0.40 0.60 199.80 8.80 98256.80 980.69 143.66 686.58 77.33 688.41 4.99 100.00
sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-0 0.00 0.00 2.20 0.00 8.80 0.00 8.00 0.21 97.27 97.27 0.00 15.64 3.44
dm-1 0.00 0.00 0.00 5.00 0.00 24.80 9.92 2.07 413.92 0.00 413.92 85.04 42.52
dm-2 0.00 0.00 0.00 196.20 0.00 99437.60 1013.64 142.98 697.27 0.00 697.27 5.10 100.00
这里重点指标是svctm和util这两列,man一下可以看到如下解释:
svctm
The average service time (in milliseconds) for I/O requests that were issued to the device.
%util
Percentage of CPU time during which I/O requests were issued to the device (bandwidth utilization for the device). Device saturation occurs when this value is close to 100%.
svctm:平均每次设备操作I/O请求的服务时间
%util:每次设备操作的IO请求中CPU时间占比,一秒中I/O 操作的利用率,或者说一秒中有多少时间 I/O 队列是非空的。如果达到100%,可以知道其实目前这台服务器的IO已经到达瓶颈了。
那为什么最前面的cpu统计图的iowait项只有5.5%左右呢?因为这个iowait(也就是top里的wa%)指的是从整体来看,CPU等待IO的耗时占比:
wa -- iowait
Amount of time the CPU has been waiting for I/O to complete.
也就是说,CPU可能拿出一部分时间来等待IO完成(iowait),但从磁盘的角度看,磁盘的利用率已经满了(util%),这种情况下,CPU使用率可能不高,但是系统整体QPS已经上不去了,如果加大流量,会导致单次IO耗时的继续增加(因为IO请求都堵在队列里了),从而影响系统整体的处理性能。
那如何规避IO负载过高的问题呢?具体问题具体分析:
- 如果你的服务器用来做日志分析,要避免多个crontab交叠执行导致多进程随机IO(参考:随机IO vs 顺序IO),避免定期的压缩、解压大日志(这种任务会造成某段时间的IO抖动)。
- 如果是前端应用服务器,要避免程序频繁打本地日志、或者异常日志等。
- 如果是存储服务(mysql、nosql),尽量将服务部署在单独的节点上,不要和其它服务共用,甚至服务本身做读写分离以降低读写压力;调优一些buffer参数以降低IO写的频率等等。另外还可以参考LevelDB这种将随机IO变顺序IO的经典方式。
svctm 一般要小于 await (因为同时等待的请求的等待时间被重复计算了),
svctm 的大小一般和磁盘性能有关,CPU/内存的负荷也会对其有影响,请求过多
也会间接导致 svctm 的增加。
await 的大小一般取决于服务时间(svctm) 以及 I/O 队列的长度和 I/O 请求的发出模式。如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;如果 await 远大于 svctm,说明 I/O 队列太长,应用得到的响应时间变慢,如果响应时间超过了用户可以容许的范围,这时可以考虑更换更快的磁盘,调整内核 elevator 算法,优化应用,或者升级 CPU。