持久化
通过持久化功能,Redis保证了即使在服务器重启的情况下也不会损失(或少量损失)数据。
RDB
RDB持久化通过保存数据库中的键值对来记录数据库状态的不同。将某个时间点上的数据库状态保存到一个RDB文件(经过压缩的二进制文件)中,通过该文件可以还原数据库状态。
RDB持久化可以手动执行,也可以根据配置定期执行。
有两个Redis命令可以生成RDB文件,一个SAVE,另一个BGSAVE;
SAVE会阻塞服务器进程,不能处理任何命令请求;
BGSAVE会派生一个子进程,服务器进程继续处理命令请求。
自动间隔性保存:通过配置选项,让服务器每隔一段时间自动执行一次BGSAVE命令。
BGSAVE会派生一个子进程执行RDB的持久化工作,当通过配置save选项设置多个保存条件,任意一个条件满足,服务器会自动执行BGSAVE命令。
Redis的服务器周期性操作函数serverCron默认每隔100毫秒会执行一次,对正在运行的服务器进行维护,它的其中一项工作就是检测save选项所设置的保存条件是否已经满足,如果满足就执行BGSAVE命令。
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:Redis 调用 fork() ,同时拥有父进程和子进程。子进程将数据集写入到一个临时 RDB 文件中。当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
AOF(Append Only File):
AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态。
AOF持久化功能的实现可以分为命令追加、文件写入、文件同步三个步骤。
AOF文件里面保存了重建数据库状态所需的所有写命令,服务器只要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。
当AOF持久化处于打开状态时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。服务器周期性操作函数serverCron会周期性调用flushAppendOnlyFile函数,并判断appendfsync值是否将aof_buf缓冲区中的内容写入和保存到AOF文件中。
AOF重写:为了解决AOF体积膨胀问题,Redis服务器会创建一个新的AOF文件替代现有的AOF文件,两个文件保存的数据库状态相同,不同的是新AOF文件不会包含任何浪费空间的冗余命令。(子进程执行,缓冲区解决不一致问题),整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。
AOF重写不会对现有AOF文件进行分析读写,而是通过读取服务器当前的数据库状态来实现。(读取数据库中现有数据,使用一条命令来代替保存在AOF文件中,例如读取list键的所有值,使用一条RPUSH命令保存)
AOF在过去曾经发生过这样的bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。
服务器可能在程序正在对AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。
使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复。
$ redis-check-aof --fix
(可选)使用 diff -u对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。
重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。
RDB和AOF使用
RDB持久化保存数据库状态是将所有的键值对保存到RDB文件中;而AOF持久化数据库状态则是将服务器执行的所有命令保存到AOF文件中。
因为AOF文件的更新频率通常比RDB文件的更新频率高,所以:
-
如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态;
-
只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态。
服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成为止。
RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。