redis 持久化 AOF和 RDB 引起的生产故障
概要
最近听开发的同事说,应用程序连接 redis 时总是抛出连接失败或超时之类的错误。通过观察在 redis 日志,发现日志中出现 "Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis." 频率极其频繁。百度了一番,提示该错误可能会造成 redis server 上的处理延迟,而且客户端上也可能发生异常或连接超时。
继续深入发现,这是因为启用了 AOF(appendonly yes),并且 appendfsync 参数为 everysec,造成的磁盘 I/O 负载高。那么本文将介绍该问题发生的原因,并给出一些建议。
故障分析
首先我们要知道,redis 是一个多路复用的单进程应用程序。多路,指的是多个网络地址,复用是指重复利用单个线程。当打开 AOF 持久化功能后, Redis 处理完每个事件后会调用 write(2) 将变化写入 kernel 的 buffer,如果此时 write(2) 被阻塞,Redis 就不能处理下一个事件。Linux 规定执行 write(2) 时,如果对同一个文件正在执行fdatasync(2)将 kernel buffer写入物理磁盘,或者有system wide sync在执行,write(2)会被Block住,整个Redis被Block住。
如果系统IO 繁忙,比如有别的应用在写盘,或者Redis自己在AOF rewrite或RDB snapshot(虽然此时写入的是另一个临时文件,虽然各自都在连续写,但两个文件间的切换使得磁盘磁头的寻道时间加长),就可能导致 fdatasync(2) 迟迟未能完成从而 Block 住 write(2),Block 住整个 Redis。而,我们的生产主库和从库都同时开启了AOF已经RDB save的方式做持久化。
为了更清晰的看到fdatasync(2)的执行时长,可以使用 "strace -p (pid of redis server) -T -e -f trace=fdatasync",但会影响系统性能。Redis提供了一个自救的方式,当发现文件有在执行 fdatasync(2) 时,就先不调用 write(2),只存在 cache 里,免得被 Block。但如果已经超过两秒都还是这个样子,则会硬着头皮执行 write(2),即使 redis 会被 Block 住。此时那句要命的 log 会打印:"Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis."。之后用redis-cli INFO 可以看到 aof_delayed_fsync 的值被加1。因此,对于 fsync 设为 everysec 时丢失数据的可能性的最严谨说法是:如果有 fdatasync 在长时间的执行,此时 redis 意外关闭会造成文件里不多于两秒的数据丢失。如果 fdatasync 运行正常,redis 意外关闭没有影响,只有当操作系统 crash 时才会造成少于1秒的数据丢失。
网上有小伙伴说,该错误在后续版本有修复。我个人这并不是一个BUG,至于真假还请小伙伴验证。
解决方法
方法一、各种修改配置
最后发现,原来是AOF rewrite时一直埋头的调用 write(2),由系统自己去触发 sync。在RedHat Enterprise 6里,默认配置vm.dirty_background_ratio=10,也就是占用了 10% 的可用内存才会开始后台 flush,而我的服务器有 8G 内存。很明显一次 flush 太多数据会造成阻塞,所以最后果断设置 "sysctl vm.dirty_bytes=33554432(32M)" 。AOF rewrite时定时也执行一下 fdatasync 嘛, antirez 回复新版中,AOF rewrite 时 32M 就会重写主动调用 fdatasync。
查看一下系统内核参数
>sysctl -a | grep dirty_background_ratio
vm.dirty_background_ratio = 10 >sysctl -a | grep vm.dirty_bytes
vm.dirty_bytes = 0
尝试修改
echo "vm.dirty_bytes=33554432" >> /etc/sysctl.conf
最后执行 "sysctl -p" 使配置生效;
方法二、关闭 RDB 或 AOF 持久化
通过上面我们知道该故障问题,其实就是因为磁盘大量IO 造成的请求阻塞。那么禁用 RDB 或 AOF 任一持久化即可,当然,建议禁用 RDB 而使用 AOF。
最后
下面再给大家一些在实际生产中的建议,以及避免这类问题的发生。首先,如果架构允许尽量不要在主库上同时做 RBD 和 AOF 持久化(如果要做,就使用SSD固态硬盘)。但是,这样如果不做持久化,将暴露如下问题:
1. 当 redis 服务挂掉之后,重启缓存全部丢失;
2. 当主机挂掉,通过脚本或sentinel将从提升为主之后,以前主库就作废;
这样做的好处就是,提升了主库的性能。坏处就是,当主库宕机之后,你只能将该主机从主从当中剔除;
上面这种方式提高了一定的复杂性,那么要解决这个问题。那么可以选择一个折中办法,那就是做AOF持久化而不使用RDB的方式。我们可以通过下面的内容来选择适合自己的持久化方式,如下;
RDB。在这里,您可以根据您配置的保存触发器进行大量权衡。
AOF + fsync 总是这样:这个速度非常慢,只有当你知道你在做什么的时候才应该使用它。
AOF + fsync 每一秒:这是一个很好的妥协。
AOF + fsync 每秒+ no-appendfsync-on-rewrite选项设置为yes:如上所示,但避免在重写期间fsync降低磁盘压力。
AOF + fsync 永远不会。 Fsyncing在这个设置上取决于内核,甚至更少的磁盘压力和延迟尖峰的风险。
至于在工作当中,如何选择,嘿嘿,那就只能结合开发需求和部门领导意见啦。
redis 持久化 AOF和 RDB 引起的生产故障的更多相关文章
- Redis - 持久化 AOF 和 RDB
Redis - 持久化 AOF 和 RDB AOF AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集. AOF 文件中的命令全部以 Redis 协议的格 ...
- redis持久化AOF与RDB
RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot). AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原 ...
- Redis持久化AOF和RDB对比
RDB持久化 AOF持久化 全量备份,一次保存整个数据库 增量备份,一次保存一个修改数据库的命令 保存的间隔较长 保存的间隔默认一秒 数据还原速度快 数据还原速度一般 save会阻塞,但bgsave或 ...
- Redis持久化————AOF与RDB模式
1. 官方说明: By default Redis asynchronously dumps the dataset on disk. This mode is good enou ...
- Redis持久化 aof和rdb的原理配置
目录 一.介绍 二.RDB持久化(全量写入) rdb原理 rdb模式 rdb触发情况 rdb优势和劣势 rdb文件配置 rdb命令配置 rdb数据恢复 三.AOF持久化(增量写入) aof原理 aof ...
- redis持久化AOF与RDB配置
AOF保存的数据方案时最完整的,如果同时开启了rdb和aof下,会采用aof方式. (1)设置数据保存到数据文件中的save规则 save 900 1 #900秒时间,至少有一条数据更新,则保 ...
- redis持久化的方式RDB 和 AOF
redis持久化的方式RDB 和 AOF 一.对Redis持久化的探讨与理解 目前Redis持久化的方式有两种: RDB 和 AOF 首先,我们应该明确持久化的数据有什么用,答案是用于重启后的数据恢复 ...
- Redis持久化——内存快照(RDB)
最新:Redis持久化--如何选择合适的持久化方式 最新:Redis持久化--AOF日志 最新:Redis持久化--内存快照(RDB) 一文回顾Redis五大对象(数据类型) Redis对象--有序集 ...
- Redis持久化——AOF日志
最新:Redis内存--内存消耗(内存都去哪了?) 最新:Redis持久化--如何选择合适的持久化方式 最新:Redis持久化--AOF日志 更多文章... 上一篇文章Redis持久化--内存快照(R ...
随机推荐
- 拖放排序插件Sortable.js 兼容好及功能全个人觉得比dragula.js 好的多
经测试,Sortable.js 兼容好和使用方便都是比较不错的,特别手机端使用很棒 介绍 Sortable.js是一款轻量级的拖放排序列表的js插件(虽然体积小,但是功能很强大)下载地址:https: ...
- ICS Hack Tools
参考链接:http://icstraining.org/en/security-tools/configurations ICS-Security-Tool: https://github.com/I ...
- Java SE之Java工作原理
在Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器.这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口.编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后 ...
- java字符串集合
一,java的接口跟C语言所能做到的相比确实是让人眼前一亮的东西.利用接口可以将多种东西放到一起,在编程过程中就能省略掉相同类的很多重复代码,将代码进行分类别的,统一的处理. 二,java中的字符串处 ...
- Activity,Fragment的状态保存
http://blog.csdn.net/hqdoremi/article/details/26376797 https://blog.csdn.net/u013588712/article/deta ...
- linux笔记_day05
1.bash以及特性 shell:外壳 GUI:KDE,Gnome,Xfce CLI:sh,csh,ksh,bash(born again shell) 进程:在每个进程看来,当前主机上只存在内核和当 ...
- Dubbo启动时检查
Dubbo在启动时会检查服务提供者所提供的服务是否可用,默认为True. (1).单个服务关闭启动时检查(check属性置为false) 1).基于xml文件配置方式 <!--3.声明需要调用的 ...
- UML和模式应用4:初始阶段(3)--需求制品之用例模型
1. 前言 UP开发包括四个阶段:初始阶段.细化阶段.构建阶段.移交阶段: UP每个阶段包括 业务建模.需求.设计等科目: 其中需求科目对应的需求制品包括:设想.业务规则.用例模型.补充性规格说明.词 ...
- Websphere MQ Cluster
大纲: 1.什么是集群 2.建立一个基本的集群 3.DISPLAY命令 4.负载均衡 5.高级配置和管理 6.答疑 7.关于文章.红宝书等 一. 什么是集群 集群就是Websphere M ...
- Nodejs 实现ESL内联FreeSWITCH设定说明
一.背景说明: SIP Server IP (Centos):192.168.11.61 ,服务器IP(Windows):192.168.11.19 二.目的: 能够从192.168.11.19上通 ...