Redis的持久化方式有2种:AOF和RDB 。持久化机制可以保证进程退出时数据丢失问题,下次重启时可以利用持久化的文件实现数据恢复。
RDB持久化
触发机制
-
手动触发
手动触发对应2个命令:save命令和bgsave命令,bgsave命令是对save命令的改进,现在save命令已经废弃。
save命令:save命令会阻塞当前Redis服务器,直到RDB完成为止,对于内存较大的 实例会造成长时间阻塞,线上环境不建议使用。 bgsave命令:Redis进程执行fork命令创建子进程,RDB持久化过程由子进程进行负 责,完成后子进程自动结束。阻塞只发生在fork阶段,一般时间很短。
-
自动触发
使用save相关配置,如save m n,即数据集在m秒内存在n次修改,触发bgsave。
主从节点进行全量复制,主节点自动执行bgsave生成RDB文件并发送给从节点。
执行debug reload命令重新加载Redis时,也会自动触发save操作。
默认情况下执行shoutdown命令时,如果没有开启AOF持久化功能则自动执行bgsave。
bgsave的执行流程
1)调用bgsave命令来进行持久化,首先在父进程中查看有没有其他正在执行的子进程,如果有,bgsave命令立即返回;
2)如果没有,则父进程调用fork命令创建子进程,此时父进程阻塞;
3)fork命令完成后,父进程不再阻塞,去响应其他命令;
4)子进程进行持久化,生成RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换;
5)子进程执行完毕后,发送信号通知父进程,父进程更新统计信息。
RDB的优缺点
优点:
(1)RDB是以一个紧凑压缩的二进制文件,代表Redis在某个时点上的数据快照。非常适用于备份,并把RDB文件拷贝到远程机器或者文件系统中,用于灾难恢复。
(2)Redis加载RDB数据恢复远远快于AOF的方式。
缺点:
(1)RDB方式数据没办法实现实时持久化/秒级持久化。
bgsave每次运行都要执行fork操作创建子进程,属于重量级的操作,频繁执行成本较高。
(2)RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版本的Redis的问题。
AOF持久化
AOF以独立日志的方式去记录每次写命令,重启时在重新执行AOF文件中的命令达到恢复数据的目的。AOF主要解决数据持久化的实时性。AOF目前是Redis持久化主流的方式。
AOF功能默认不开启,可通过appendonly yes 开启,文件名通过Appendfilename设置,默认为appendonly.aof。
AOF的工作流程操作:命令写入,文件同步,文件重写,重启加载。
流程如下:
1)所有的写入命令会追加到aof_buf(缓冲区)中;
2)AOF缓冲区根据对应的策略向硬盘做同步操作;
3)随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的;
4)当Redis服务器重启时,可以加载AOF文件进行数据恢复;
命令写入
采用文本协议格式进行命令写入,有3点考虑:
1)文本协议具有很好的兼容性;
2)直接采用协议格式,这样在追加命令时避免了二次处理开销;
3)文本协议具有可读性,方便直接修改和处理。
文件同步
可根据appendfsync参数来设置同步策略:
always:每次写入都要同步AOF文件,不建议设置;
no:同步由操作系统负责,由于操作系统每次同步AOF的文件周期不可控,而且会加大每次同步硬盘的数据量,虽然提升了性能,但数据安全无法保证。
everysec: 默认配置,也是建议的配置策略。做到兼顾性能和数据安全性。
重写机制
重写机制是为了防止随着时间的推移,文件变得越来越大的问题。通过重写机制,文件体积可以变小.
1)重写时不写已经过期的数据;
2)新的AOF文件只保留最终数据的写入命令,旧的无效命令不写入;
3)多条写入命令可以合并为一个;
重写机制的运作流程:
过程如下:
1)执行AOF重写请求 。
如果当前进程正在执行AOF重写,请求不执行并返回相关响应。
如果当前进程正在执行bgsave操作,重写命令延迟到bgsave命令执行后执行,并返回相关
响应。
2)父进程调用fork来创建子进程。
3.1)主进程创建fork完成后,继续响应其他命令。所有修改命令依然写入AOF缓冲区并根据appendsyc策略同步到硬盘,保证原有AOF机制的正确性;
3.2)由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存,而父进程依然响应命令,Redis使用AOF重写缓冲区来缓存这部分数据,防止新AOF生成期间丢失这部分数据。
4)子进程根据内存快照,按照命令合并规则写入到新的AOF文件。
5.1)子进程写入完成后,发送信号给父进程,父进程更新统计信息。
5.2)父进程把AOF重写缓冲区的数据写入到新的AOF文件中。
5.3)使用新的AOF文件替换老文件,完成AOF读写。
重启加载
重启加载的过程如下:
1)持久化开启且存在AOF文件时,优先加载AOF文件。
2)AOF关闭或者AOF文件不存在时,加载RDB文件。
3)加载AOF/RDB文件成功后,Redis启动成功。
4)加载AOF/RDB文件失败后,Redis启动失败,打印失败信息。
RDB和AOF的对比
RDB
优点:
1)RDB文件紧凑,适合每隔一段时间进行备份的场景,这样数据恢复时,可以将数据集还原到不同版本;
2)适用于灾难恢复。RDB文件只有一个,非常紧凑;
3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
缺点:
1)RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。所以要尽量避免在服务器故障时丢失数据,那么 RDB 不适合。
2)每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork()可能会非常耗时,造成服务器在某某毫秒内停止处理客户端。
AOF
优点:
使用 AOF 持久化会让 Redis 变得非常耐久。AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据。
缺点:
1)AOF 文件的体积通常要大于 RDB 文件的体积,灾难恢复效率低。