Redis时延问题分析及应对( 三 )


我们来梳理下:
1) 起因:有大量IO操作write(2) 但未主动调用同步操作
2) 造成kernel buffer中有大量脏数据
3) 系统同步时,sync的同步时间过长
4) 造成redis的写aof日志write(2)操作阻塞;
5) 造成单线程的redis的下一个事件无法处理,整个redis阻塞(redis的事件处理是在一个线程中进行,其中写aof日志的write(2)是同步阻塞模式调用,与网络的非阻塞write(2)要区分开来)
产生1)的原因:这是redis2.6.12之前的问题,AOF rewrite时一直埋头的调用write(2),由系统自己去触发sync 。
另外的原因:系统IO繁忙,比如有别的应用在写盘;
解决方案:
控制系统sync调用的时间;需要同步的数据多时,耗时就长;缩小这个耗时,控制每次同步的数据量;通过配置按比例(vm.dirty_background_ratio)或按值(vm.dirty_bytes)设置sync的调用阈值;(一般设置为32M同步一次)
2.6.12以后,AOF rewrite 32M时会主动调用fdatasync;
另外,Redis当发现当前正在写的文件有在执行fdatasync(2)时,就先不调用write(2),只存在cache里,免得被block 。但如果已经超过两秒都还是这个样子,则会强行执行write(2),即使redis会被block住 。
AOF重写完成后合并数据时造成的阻塞
在bgrewriteaof过程中,所有新来的写入请求依然会被写入旧的AOF文件,同时放到AOF buffer中,当rewrite完成后,会在主线程把这部分内容合并到临时文件中之后才rename成新的AOF文件,所以rewrite过程中会不断打印"Background AOF buffer size: 80 MB,Background AOF buffer size: 180 MB",要监控这部分的日志 。这个合并的过程是阻塞的,如果产生了280MB的buffer,在100MB/s的传统硬盘上,Redis就要阻塞2.8秒;
解决方案:
将硬盘设置的足够大,将AOF重写的阈值调高,保证高峰期间不会触发重写操作;在闲时使用crontab 调用AOF重写命令;
参考:
http://www.oschina.net/translate/redis-latency-problems-troubleshooting
https://github.com/springside/springside4/wiki/redis
原文地址:https://www.cnblogs.com/me115/p/5032177.htmlJAVA编程技术乐园:一个分享编程知识 。跟着老司机一起学习干货技术知识,每天进步一点点,让小的积累,带来大的改变!
欢迎关注!持续推送有趣有料的技术文章~

【Redis时延问题分析及应对】


推荐阅读