# 一、Redis 持久化方式(RDB)

【1】RDB(Redis DataBase): 在指定的时间间隔内将内存中的数据集以快照的形式写入磁盘,也就是行话讲的 Snapshot (快照),它恢复时是将快照文件直接读到内存里。Redis 会单独创建(Fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何 IO操作的(Fork 子进程的时候,主线程会消耗一点性能),这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF方式更加的高效。RDB 的缺点是最后一次持久化后的数据可能丢失,RDB 保存的是 dump.rdb文件。快照也是默认实现 Reids 持久化数据的方式。快照是一种全量备份,快照是内存数据的二进制序列化形式,在存储上非常紧凑。

Fork:作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但新进程是一个全新的进程,并作为原进程的子进程。

【2】触发 RDB 快照: 支持手动触发和自动触发两种模式:①、自动触发:在 redis.conf 配置文件中的 SNAPSHOTTING 下,通过配置 save 触发 Redis 的持久化条件。当达到如下条件时,会自动触发 bgsave 命令。当然如果只是用 Redis 的缓存功能,不需要持久化。可以注释掉所有的 save 行。

###########################SNAPSHOTTING##############################
save 900 1      #900 秒内如果超过 1 个 key 被修改,则发起快照保存
save 300 10     #300秒超过10个key被修改,发起快照
save 60 10000   #60秒超过10000个key被修改,发起快照
1
2
3
4

从节点全量复制[自动触发快照]:从节点执行全量复制操作时,主节点执行 bgsave生成 rdb文件发送给从节点。(主从复制是通过 RDB快照进行的)。执行 debug reload 命令重新加载 Redis时,也会触发 save操作。默认情况下执行 shutdown 时,如果没有开启 AOF 持久化,则自动执行 bgsave。

②、手动触发:Redis 进行 RDB持久化的命令有两种:save 与 bgsave:
 ■ save:该命令会阻塞当前 Reids 服务器,执行 save 命令期间,Redis 不能处理其他命令,直到 RDB 过程完成为止。显然该命令对于内存比较大的实例会造成长时间阻塞,这是致命的缺陷。
 ■ bgsave:Redis 会在后台异步进行快照操作。快照同时还可以响应客户端请求。具体操作是 Redis 进程执行 fork 操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在 fork阶段,一般时间很短。基本上 Redis 内部所有的 RDB 操作都是采用 bgsave 命令。

Cluster

【3】RDB 常用配置信息: ☛ 快照同时还可以响应客户端请求。可以通过 lastsave 命令获取最后一次成功执行快照的时间。
☛ 执行 flushall 命令,也会产生 dump.rdb 文件,但里面是空的,无意义。
☛ 如何恢复:将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。
☛ CONFIG GET dir 获取目录。

【4】RDB 优势:
 1)、RDB默认采用 LZF 算法对生成的文件做压缩,RDB文件是一个紧凑压缩的二进制文件,适合备份、全量复制
 2)、Redis 加载 RDB 的速度远远大于 AOF 的方式。
 3)、适合大规模的数据恢复且对数据完整性和一致性要求不高。

【5】RDB 劣势:
 1)、RDB 的备份方式无法做到实时持久化、秒级持久化,不能完全保证数据安全,在两个备份点之间可能会发生数据丢失。在一定间隔时间做一次备份,所以如果 Redis 意外 Down掉的话,就会丢失最后一次快照后的所有修改。
 2)、RDB 频繁操作执行成本较高。
 3)、RDB 文件演进过程中存在多个格式的 RDB版本,存在老版本无法兼容新版本 RDB格式的问题。
 4)、Fork 的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。

【6】如何停止: 动态停止所有RDB保存规则的方法:redis-cli config set save ""

# 二、Redis 持久化方式(AOF)

【1】AOF(Append Only File): 以日志的形式来记录每个写操作,将 Redis 执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,Redis 启动之初会读取该文件重新构建数据,换言之,Redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作,AOF 保存的是 appendonly.aof 文件。AOF 解决了数据持久化的实时性,但恢复较为耗时。

【2】AOF 的工作机制:
 ■ 命令写入:服务器执行一次写命令后以纯文本格式将被执行的命令(如SET/RPUSH)追加到服务器状态的 aof_buf 缓存区的末尾。
 ■ AOF 缓冲:服务器在每次结束一个事件循环之前,它都会调用 flushAppendOnlyFile 函数,考虑是否需要将 aof_buf 缓冲区中的内容写入和保存到 AOF 文件里面。
 ■ AOF 文件重写:Redis 提供 AOF 重写机制以压缩 AOF 文件的体积。

rewrite(重写)是什么: AOF 采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当 AOF 文件的大小超过所设定的阈值时,Redis 就会启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof

 ■ 数据恢复:Reids 重启时如果启动了 AOF,则加载 AOF 文件,加载成功则启动成功,加载失败则启动失败。

Cluster

【3】重写原理: AOF 文件持续增长而过大时,会 fork 出一条子进程来将文件重写(也是先写临时文件最后再 rename),遍历新进程的内存中数据,每条记录有一条的 Set语句。重写 aof 文件的操作,并没有读取旧的 aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的 aof文件,这点和快照有点类似。Redis 提供了 bgrewriteaof指令用于对 AOP日志瘦身。

【4】AOF 正常恢复:
 ✔ 启动:设置Yes:修改默认的 appendonly no,改为 yes
 ✔ 将数据的 aof 文件复制一份保存到对应目录(config get dir)
 ✔ 恢复:重启 redis 然后重新加载

【5】AOF异常恢复:
 ✔ 启动:设置 Yes:修改默认的 appendonly no,改为yes
 ✔ 备份被写坏的 AOF 文件
 ✔ 修复:redis-check-aof --fix进行修复
 ✔ 恢复:重启 redis 然后重新加载

【6】触发机制: Redis会记录上次重写时的 AOF大小,默认配置是当 AOF文件大小是上次 rewrite后大小的一倍且文件大于64M时触发。

【7】AOF同步策略: AOF 日志是以文件的形式存在的,当程序对 AOF 日志文件进行写操作时,实际上是将内容写到了内核为文件描述符分配的一个内存缓存中,然后内核会异步将数据刷回到磁盘的。这就意味着如果机器突然宕机,AOF 日志内容可能还没有来得及完全刷新到磁盘中,这个时候就会出现日志丢失。但Linux 的 glibc 提供了 fsync(int fd) 函数可以将指定文件的内容强制从内核缓存刷新到磁盘。只要 Reids进程实时调用 fsync函数就可以保证 AOF日志不丢失。但是 fsync 是一个磁盘 IO 操作,它很慢,对性能影响很大。
 1)、每修改同步配置[appendfsync always]:同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好。
 2)、每秒同步[appendfsync everysec] :异步操作,每秒记录。如果一秒内宕机,有数据丢失。这在数据安全性和性能性能之间做了一个折中,在保持高性能的同时,尽可能使数据少丢失。
 3)、不同步[appendfsync no]:从不同步。

【8】AOF 优势: ①、采用 AOF 时,数据的备份粒度更小,数据较安全。②、AOF 会对日志文件进行追加操作,不修改已经写好的内容。即使断电的情况下,AOF 日志仍然是可用的。

【9】AOF劣势: ①、相同数据集的数据而言 AOF文件要远大于 RDB文件,恢复速度慢于 RDB。②、AOF 使用 fsync策略,运行效率要慢于RDB,每秒同步策略效率较好,不同步效率和 RDB相同。

# 三、Redis 数据恢复

当 Redis 服务器挂掉时,重启将按照如下优先级恢复数据到内存中:

【1】如果只配置了 AOF,重启加载 AOF 文件进行恢复。

【2】如果同时配置了 AOF 和 RDB,启动时只加载 AOF 文件恢复数据。

【3】如果只配置了 RDB 启动时将加载 dump 文件恢复数据。

Cluster

# 四、总结(Which one)

【1】RDB 持久化方式能够在指定的时间间隔对你的数据进行快照存储。

【2】AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF 命令以 Redis协议追加保存每次写的操作到文件末尾。Redis还能对 AOF文件进行后台重写,使得 AOF文件的体积不至于过大。

【3】只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。

【4】为什么会优先载入 AOF文件来恢复原始的数据:因为在通常情况下 AOF文件保存的数据集要比 RDB文件保存的数据集要完整。RDB的数据不实时存储,同时使用两者时服务器重启也只会找 AOF文件。那要不要只使用 AOF呢? 作者建议不要,因为 RDB 更适合用于备份数据库(AOF 在不断变化不好备份),快速重启,而且不会存在 AOF可能潜在的 bug,留着作为一个万一的手段。

(adsbygoogle = window.adsbygoogle || []).push({});