redis持久化详解之AOF
AOF持久化跟RDB不同,它是将写命令记录到日志中,并将这些写操作保存到aof文件中
使用AOF
开启aof需要开启配置:appendonly yes ,默认不开启,aof文件名通过appendfilename 配置,默认文件名 APPendonly.aof ;保存路径跟RDB相同,通过 dir 配置
持久化配置
#启用aof持久化方式
appendonly yes
#每次收到写命令就立即强制写入磁盘, 最慢的大概只有几百的TPS, 但是保证完全的持久化, 不推荐使用
appendfsync always
#每秒钟强制写入磁盘一次, 在性能和持久化方面做了很好的折中, 推荐
appendfsync everysec
#完全依赖os 性能最好,持久化没保证,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的 对大多数Linux操作系统是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。
appendfsync no,
工作流程
- 所有的写入命令都会写入到缓存区
- aof缓冲区根据对应的策略向硬盘做同步操作
- 随着文件越来愈大需要定期对aof文件重写,达到压缩的目的
- 当redis重启时,可以通过aof文件恢复
重写机制
aof是将写操作追加到aof文件后面,随着写入的越来约到,文件会越来愈大,为了解决这个问题,redis引入了aof重写机制压缩文件体积
aof重写是把redis进程内的数据转化为写操作同步到aof文件的过程
比如:
多条写命令可以合并为一个, 如: lpush list a、 lpush list b、 lpush list c 可以转化为: lpush list a b c。
aof重写降低了文件大小,并且aof文件可以更快的被redis加载
触发机制
aof重写可以手动触发跟自动触发
手动触发 :调用bgrewriteaof 命令。
自动触发:根据auto-aof-rewrite-min-size和 auto-aof-rewrite-percentage参数确定自动触发时机
auto-aof-rewrite-min-size: 表示运行 AOF 重写时文件最小体积, 默认为 64MB。
auto-aof-rewrite-percentage: 代表当前 AOF 文件空间(aof_current_size) 和上一次重写后 AOF 文件空间(aof_base_size) 的比值
示例:
auto-aof-rewrite-percentage: 100
auto-aof-rewrite-min-size: 64mb
默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发
重写运行流程
- 1.开始重写
- 2.父进程执行 fork 创建子进程, 开销等同于 bgsave 过程
- 3.1 主进程 fork 操作完成后, 继续响应其他命令。 所有修改命令依然写入 AOF 缓冲区并根据 appendfsync 策略同步到硬盘,保证原有 AOF 机制正确性。.
- 3.2 由于 fork 操作运用写时复制技术, 子进程只能共享 fork 操作时的内存数据。 由于父进程依然响应命令, Redis 使用“AOF 重写缓冲区”保存这部分新数据, 防止新 AOF 文件生成期间丢失这部分数据
- 4. 子进程根据内存快照, 按照命令合并规则写入到新的 AOF 文件。 每次批量写入硬盘数据量由配置 aof-rewrite-incremental-fsync 控制, 默认为 32MB, 防止单次刷盘数据过多造成硬盘阻塞。
- 4.1) 新 AOF 文件写入完成后, 子进程发送信号给父进程, 父进程更新统计信息, 具体见 info persistence 下的 aof_*相关统计。
4.2) 父进程把 AOF 重写缓冲区的数据写入到新的 AOF 文件。
4.3) 使用新 AOF 文件替换老文件, 完成 AOF 重写。
AOF注意事项
在写入aof日志文件时, 如果Redis服务器宕机, 则aof日志文件文件会出格式错误, 在重启Redis服务器时, Redis服务器会拒绝载入这个aof文件,可以通过命令修复aof并恢复数据
redis-check-aof -fix file.aof
AOF的优点
- 可以设置完全不同步,每秒同步,每次同步,默认每秒,因为aod是写操作的追加,所以可以频繁的大量的的同步
- aof是日志追加的文件,所以服务器宕机也可以通过redis-check-aof工具修复
- 如果aof文件过大,redis会在后台自动重写aof文件。压缩到最小指令集
- AOF文件是有序保存数据库的所有写入操作, 易读, 易分析。 即使如果不小心误操作数据库, 也很容易找出错误指令, 恢复到某个数据节点。 例如不小心FLUSHALL, 可以非常容易恢复到执行命令之前。
AOF的缺点
- 相同数据量下,aof文件通常回避rdb大,因为aof存的是指令,而rdb存的是数据快照。
- 在大量写入跟载入的时候rdb会比aof快很多,因为大量写入。aof会执行更多的保存命令,载入也需要大量执行命令来得到结果
持久化的选择
在实际生产环境中, 根据数据量、 应用对数据的安全要求、 预算限制等不同情况, 会有各种各样的持久化策略; 如完全不使用任何持久化、 使用RDB或AOF的一种, 或同时开启RDB和AOF持久化等。 此外, 持久化的选择必须与Redis的主从策略一起考虑, 因为主从复制与持久化同样具有数据备份的功能,而且主机master和从机slave可以独立的选择持久化方案。面分场景来讨论持久化策略的选择, 下面的讨论也只是作为参考, 实际方案可能更复杂更具多样性。
1) 如果Redis中的数据完全丢弃也没有关系(如Redis完全用作DB层数据的cache) , 那么无论是单机,
还是主从架构, 都可以不进行任何持久化。
2) 在单机环境下(对于个人开发者, 这种情况可能比较常见) , 如果可以接受十几分钟或更多的数据丢失, 选择RDB对Redis的性能更加有利;如果只能接受秒级别的数据丢失, 应该选择AOF。
3) 但在多数情况下, 我们都会配置主从环境, slave的存在既可以实现数据的热备, 也可以进行读写分离分担Redis读请求,以及在master宕掉后继续提供服务。在这种情况下的做法是:
master: 完全关闭持久化(包括RDB和AOF) , 这样可以让master的性能达到最好;
slave: 关闭RDB, 开启AOF(如果对数据安全要求不高, 开启RDB关闭AOF也可以) , 并定时对持久化文件进行备份(如备份到其他文件夹, 并标记好备份的时间) ;然后关闭AOF的自动重写, 然后添加定时任务, 在每天Redis闲时(如凌晨12点) 调用bgrewriteaof。
这里需要解释一下, 为什么开启了主从复制, 可以实现数据的热备份, 还需要设置持久化呢? 因为在一些特殊情况下, 主从复制仍然不足以保证数
据的安全, 例如:
- master和slave进程同时停止: 考虑这样一种场景, 如果master和slave在同一个机房, 则一次停电事故就可能导致master和slave机器同时关机,
- Redis进程停止; 如果没有持久化, 则面临的是数据的完全丢失。
- master误重启: 考虑这样一种场景, master服务因为故障宕掉了, 如果系统中有自动拉起机制(即检测到服务停止后重启该服务) 将master自动重启, 由于没有持久化文件, 那么master重启后数据是空的,
- slave同步数据也变成了空的; 如果master和slave都没有持久化, 同样会面临数据的完全丢失。 需要注意的是, 即便是使用了哨兵进行自动的主从切换,也有可能在哨兵轮询到master之前, 便被自动拉起机制重启了。 因此, 应尽量避免“自动拉起机制”和“不做持久化”同时出现。
4) 异地灾备: 上述讨论的几种持久化策略, 针对的都是一般的系统故障, 如进程异常退出、 宕机、 断电等, 这些故障不会损坏硬盘。 但是对于一些可能导致硬盘损坏的灾难情况, 如火灾地震, 就需要进行异地灾备。
例如对于单机的情形, 可以定时将RDB文件或重写后的AOF文件, 通过scp拷贝到远程机器, 如阿里云; 对于主从的情形, 可以定时在master上执行bgsave, 然后将RDB文件拷贝到远程机器,或者在slave上执行bgrewriteaof重写AOF文件后, 将AOF文件拷贝到远程机器上。一般来说, 由于RDB文件文件小、 恢复快, 因此灾难恢复常用RDB文件; 异地备份的频率根据数据安全性的需要及其它条件来确定, 但最好不要低于一天一次。
持久化配置方案
1、 企业级的持久化的配置策略
save 60 10000: 如果你希望尽可能确保说, RDB最多丢1分钟的数据, 那么尽量就是每隔1分钟都生成一个快照, 低峰期, 数据量很少, 也没必要
10000->生成RDB, 1000->RDB, 这个根据你自己的应用和业务的数据量, 你自己去决定
AOF一定要打开, fsync, everysec
auto-aof-rewrite-percentage 100: 就是当前AOF大小膨胀到超过上次100%, 上次的两倍
auto-aof-rewrite-min-size 64mb: 根据你的数据量来定, 16mb, 32mb
2、 数据备份方案
RDB非常适合做冷备, 每次生成之后, 就不会再有修改了
数据备份方案
(1) 写crontab定时调度脚本去做数据备份
(2) 每小时都copy一份rdb的备份, 到一个目录中去, 仅仅保留最近48小时的备份
(3) 每天都保留一份当日的rdb的备份, 到一个目录中去, 仅仅保留最近1个月的备份
(4) 每次copy备份的时候, 都把太旧的备份给删了
(5) 每天晚上将当前服务器上所有的数据备份, 发送一份到远程的云服务上去【crontab】
AOF常用配置总结
appendonly no: 是否开启AOF
appendfilename "appendonly.aof": AOF文件名
dir ./: RDB文件和AOF文件所在目录
appendfsync everysec: fsync持久化策略
no-appendfsync-on-rewrite no: AOF重写期间是否禁止fsync; 如果开启该选项, 可以减轻文件重写时CPU和硬盘的负载(尤其是硬盘) , 但是可能会丢失
AOF重写期间的数据; 需要在负载和安全性之间进行平衡
auto-aof-rewrite-percentage 100: 文件重写触发条件之一
auto-aof-rewrite-min-size 64mb: 文件重写触发提交之一
aof-load-truncated yes: 如果AOF文件结尾损坏, Redis启动时是否仍载入AOF文件