wind-snow

因为 Redis 是内存数据库,它将自己的数据储存在内存里面,所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面,那么一旦服务器进程退出,服务器中的数据也将会丢失,为了解决这个问题,Redis 提供了持久化的功能。

Redis 中的持久化有两种,分别是 RDB 和 AOF。

RDB 持久化

RDB 是将 Redis 内存中的快照直接保存到磁盘中,避免数据丢失。

RDB 文件的创建

RDB 文件是一个经过压缩的二进制文件。有两个命令可以生产 RDB 文件,一个是 SAVE,另一个是 BGSAVE。
save 命令会阻塞 Redis 服务器进程,直到 RDB 文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。
BGSAVE 命令会派生出一个子进程,然后由子进程负责创建 RDB 文件,服务器进程(父进程)继续处理命令请求。

除了主动执行命令之外,Redis 还可以根据配置自动进行 RDB 持久化。如果我们向服务器有如下配置(默认就有):
save 900 1
save 300 10
save 60 10000
那么只要满足以下三个条件中的任意一个,BGSAVE 命令就会被执行:

  • 服务器在 900 秒之内,对数据库进行了至少 1 次修改。
  • 服务器在 300 秒之内,对数据库进行了至少 10 次修改。
  • 服务器在 60 秒之内,对数据库进行了至少 10000 次修改。

RDB 文件的载入

RDB 文件的载入工作是在服务器启动时自动执行的,所以 Redis 并没有专门用于载入 RDB 文件的命令,只要 Redis 服务器在启动时检查到 RDB 文件,就会自动载入。

另外值得一提的是,因为 AOF 文件的更新频率通常比 RDB 文件的更新频率高,所以:

  • 如果服务器开启了 AOF 持久化功能,那么服务器会优先使用 AOF 文件来还原数据库状态。
  • 只有在 AOF 持久化功能处于关闭状态时,服务器才会使用 RDB 文件来还原数据库状态。
    如下图所示(出自《Redis设计与实现第二版》第十章:RDB持久化):

《Redis设计与实现第二版》

AOF 持久化

和 RDB 持久化不同,AOF 持久化是通过保存 Redis 服务器所执行的谢明令来记录数据库状态的,如下图所示(出自《Redis设计与实现第二版》第十一章:AOF持久化):

《Redis设计与实现第二版》

AOF 持久化的实现

当 AOF 持久化功能处于打开状态时,服务器在执行完一个写命令之后,会讲被执行的写命令追加到服务器状态的 aof_buf 缓冲区的末尾。
Redis 服务器会每隔 100ms 将 aof_buf 缓冲区的内容真正写入到 AOF 文件里面。

AOF 持久化的效率和安全性
服务器配里 appendfsync 选项的值直接决定 AOF 持久化功能的效率和安全性。

  • 当 appendfsyn 的值为 always 时,服务器在每个事件循环都要将 aof_buf 缓冲区中的所有内容写入到 AOF 文件,并且同步 AOF 文件,所以 always 的效率是 aPPendfsync 选项三个值当中最慢的一个,但从安全性来说, always 也是最安全的,因为即使出现故障停机, AOF 持久化也只会丢失一个事件循环中所产生的命令数据。
  • 当 appendfsync 的值为 everysec 时,服务器在每个事件循环都要将 aof_buf 缓冲区中的所有内容写入到 AOF 文件,并且每隔一秒就要在子线程中对 AOF 文件进行一次同步。从效率上来讲, everysec 模式足够快,并且就算出现故障停机,数据库也只丢失一秒钟的命令数据。
  • 当 appendfsync 的值为 no 时,服务器在每个事件循环都要将 aof_buf 缓冲区中的所有内容写入到 AOF 文件,至于何时对 AOF 文件进行同步,则由操作系统控制。因为处于 no 模式下的 flushAppendonlyFile 调用无须执行同步操作,所以该模式下的 AOF 文件写入速度总是最快的,不过因为这种模式会在系统缓存中积取一段时间的写入数据,所以该模式的单次同步时长通常是三种模式中时间最长的。从平摊操作的角度来看, no 模式和 everysec 模式的效率类似,当出现故障停机时,使用 no 模式的服务器将丢失上次同步 AOF 文件之后的所有写命令数据。

AOF 文件的载入与数据还原

因为 AOF 文件里面包含了重建数据库状态所需的所有写命令, 所以服务器只要读入并重新执行一遍 AOF 文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。

AOF 文件载入过程如下(出自《Redis设计与实现第二版》第十一章:AOF持久化):

《Redis设计与实现第二版》

因为 AOF 持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝, AOF 文件中的内容会越来越多,文件的体积也会越来越大,如果不加以控制的话,体积过大的 AOF 文件很可能对 Redis 服务器、甚至整个宿主计算机造成影响,并且 AOF 文件的体积越大,使用 AOF 文件来进行数据还原所需的时间就越多。

为了解决 AOF 文件体积过大的问题,Redis 提供了 AOF 文件重写功能。即服务器可以创建一个新的 AOF 文件来代替现有的 AOF 文件,但由于新的 AOF 文件不会包含任何浪费空间的冗余命令(即只有写命令,没有del命令等),所以新 AOF 文件的体积通常比旧 AOF 文件的体积小得多。

相关文章: