这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
简介
Redis 中一共有两种持久化机制:
RDB:Redis默认采用RDB持久化机制,该机制又被称作快照snapshot。AOF:是英文append-only file的缩写,意为只进行追加操作的文件。
如果同时采用了两种持久化机制,Redis 重启后会优先使用 AOF 文件来还原数据集,因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。
RDB 持久化机制
RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照 point-in-time snapshot,它先对数据集进行压缩,然后保存为二进制文件。
在 /etc/redis/redis.conf 中可以看到有关 RDB 持久化的三行配置,均以 save 开头:
save 900 1
save 300 10
save 60 10000
它们分别表示:
900秒内数据集至少有1个键被改动时,自动保存数据集300秒内数据集至少有10个键被改动时,自动保存数据集60秒内数据集至少有10000个键被改动时,自动保存数据集
Redis 将 RDB 快照保存在二进制文件中,该文件的存储路径和文件名由两个配置项决定:
dir /var/lib/redis:指定了RDB文件的存储目录为/var/lib/redisdbfilename dump.rdb:指定了RDB文件名为dump.db- 所以,
RDB机制的数据库文件会被保存到/var/lib/redis/dump.rdb中
如果想要关闭 RDB 存储机制,只需要将 /etc/redis/redis.conf 文件中的 save 开头的配置都注释掉即可:
# save 900 1
# save 300 10
# save 60 10000
当然,需要重启 redis-server 服务才会生效:
sudo service redis-server restart
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
Redis调用fork(),同时拥有父进程和子进程。- 子进程将数据集写入到一个临时
RDB文件中。 - 当子进程完成对新
RDB文件的写入时,Redis用新RDB文件替换原来的RDB文件,并删除旧的RDB文件。
写时复制
copy-on-write机制。
AOF 持久化机制
AOF 持久化记录服务器执行的所有写操作命令,新命令会被追加到文件的末尾。在 Redis 重新启动的时候,可以重新执行这些命令来还原数据集。
AOF 持久化机制默认是关闭的,在 /etc/redis/redis.conf 中可以看到它的配置:
appendonly no
只需要将 no 改成 yes 即可开启 AOF 持久化:
appendonly yes
AOF 文件的存储路径和文件名由以下两个配置决定:
dir /var/lib/redis:指定了AOF文件的存储目录为/var/lib/redisappendfilename "appendonly.aof":指定了AOF文件的文件名为appendonly.aof
AOF 同步速率的配置有三项,选用一项即可:
appendfsync everysec:默认配置,每秒同步一次。这是可以兼顾速度和安全性的配置,推荐使用。appendfsync always:只要发生改动就同步。非常慢,也非常安全。appendfsync no:采用操作系统的同步机制,通常是每30秒同步一次。
对于 AOF 文件,经常会出现冗余的中间操作,Redis 支持在不打断客户端的情况下,对 AOF 文件进行重建 rebuild。执行 BGREWRITEAOF 命令,Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。
相关配置:
auto-aof-rewrite-percentage 100 # 指当前aof文件比上次重写的增长比例大小,达到这个大小就进行 aof 重写
auto-aof-rewrite-min-size 64mb # 最开始aof文件必须要达到这个文件时才触发,后面的每次重写就不会根据这个变量了
以上配置的意思是:
在 AOF 文件小于64mb 的时候不进行重写,当到达 64mb 的时候,就重写一次。重写后的 AOF 文件可能是 10mb。上面配置了 auto-aof-rewrite-percentage 100,即 AOF 文件到了 20mb 的时候,又开始重写一次。以此类推。
AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制。以下是 AOF 重写的执行步骤:
Redis执行fork(),现在同时拥有父进程和子进程。- 子进程开始将新
AOF文件的内容写入到临时文件。 - 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有
AOF文件的末尾: 这样即使在重写的中途发生停机,现有的AOF文件也还是安全的。 - 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新
AOF文件的末尾。 - 原子地用新文件替换旧文件,之后所有命令都会直接追加到新
AOF文件的末尾。
RDB 和 AOF 的优缺点
RDB 的优点:
RDB快照文件经过压缩后非常紧凑,适用于备份和灾难恢复,而且还能选择恢复到不同的版本。RDB在恢复大数据集时的速度比AOF要快。
RDB 的缺点:
- 当需要保存的数据集非常庞大时,可能会至少
5分钟才保存一次RDB文件,如果服务器发生故障,会丢失这一段时间内的数据。 - 父进程在保存
RDB文件时是通过fork一个子进程完成的,当数据集非常庞大时,fork可能会非常耗时,造成服务器在一段时间内停止处理客户端。
AOF 的优点:
AOF持久化会让Redis变得非常健壮much more durable,如果采用默认配置,一秒钟fsync一次,就算发生故障,最多只会丢失一秒钟的数据。AOF文件是一个只进行追加操作的日志文件append only log,因此对AOF文件的写入不需要进行seek。AOF文件体积过大时,Redis会在后台对其自动重写(rewrite机制),重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合。 一旦新AOF文件创建完毕,Redis就会从旧AOF文件切换到新AOF文件,并开始对新AOF文件进行追加操作。AOF文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以Redis协议的格式保存, 因此AOF文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。
如果不小心
flushall了一下,只要AOF文件未被重写,就可以移除AOF文件末尾的命令,重启Redis即可恢复到之前的数据集。
AOF 的缺点:
- 对于相同的数据集来说,
AOF文件的体积通常要大于RDB文件的体积。 - 根据所使用的
fsync策略,AOF的速度可能会慢于RDB。 在一般情况下, 每秒fsync的性能依然非常高, 而关闭fsync可以让AOF的速度和RDB一样快, 即使在高负荷之下也是如此。 AOF在过去曾经发生过这样的bug:因为个别命令的原因,导致AOF文件在重新载入时,无法将数据集恢复成保存时的原样。 虽然这种bug在AOF文件中并不常见, 但是对比来说,RDB几乎是不可能出现这种bug的。
混合持久化
在 Redis 4.x 及以后的版本,可以两种缓存机制混合使用。两种机制共存于同一份二进制文件,先使用 RDB 持久化全量数据,再使用 AOF 持久化增量数据。
相关配置:
aof-use-rdb-preamble yes # yes:开启,no:关闭
混合持久化同样也是通过 bgrewriteaof 完成的,不同的是当开启混合持久化时,fork 出的子进程先将共享的内存副本全量的以 RDB 方式写入 AOF 文件,然后在将 aof_rewrite_buf 重写缓冲区的增量命令以 AOF 方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的 AOF 文件。
简单的说,新的 AOF 文件前半段是 RDB 格式的全量数据后半段是 AOF 格式的增量数据。