redis的持久化有3种:

  • RDB持久化
  • AOF持久化
  • RDB-AOF混合持久化

15.1 RDB 持久化

  • redis默认使用RDB
  • 将数据库中存储的键值对数据存放在一个经过压缩的二进制文件中,文件的扩展类型为.rdb
  • 有几种方式创建rbd文件:
    • SAVE
      • 阻塞服务器并创建 RDB 文件
      • 若存在旧的rdb文件则覆盖
    • BGSAVE
      • 以非阻塞的方式创建 RDB 文件
      • 以创建子进程的方式创建RDB文件
      • 当创建完成后子进程会通知主进程创建完成,并用新文件替换之前的旧文件
      • 注意:如果父进程占用的内存数量非常大,那么在fork子进程时仍然可能造成短暂的阻塞
    • 通过配置选项自动创建RDB文件
      • save <seconds> <changes> 服务器在seconds秒内至少执行了changes次修改,那么服务器会自动执行一次 BGSAVE 命令
      • 可以同时使用多个上述命令,任一命令满足时就会执行一次
      • 默认配置:
        • save 60 10000
        • save 300 100
        • save 3600 1
  • RDB 文件结构
    • RDB 文件结构

    • RDB 文件标识符

    • 版本号

      • 新版服务器总是能够向下兼容旧版redis服务器生成的RDB文件
    • 设备附加信息

      • 包含服务器版号、宿主机的架构、创建RDB文件的时间戳、服务器占用的内存数量
    • 数据库数据

      • 按顺序存放数据库数据,从0到n
      • 结构如下:
        • 数据库号码
        • 键值对总数量
        • 带有过期时间的键值对数量
        • 键值对数据部分
          • RDB 文件将以无序方式记录数据库包含的键值对
          • 数据库中的每个键值对都会被划分为最多5个部分:
            • 过期时间(可选),毫秒精度的UNIX时间戳
            • LRU信息(可选)
            • LFU信息(可选)
            • 类型
    • lua脚本缓存

    • EOF

    • CRC64校验和

      • 服务器在读入 RDB 文件时会通过这个校验和来快速地检查 RDB 文件是否出错或者损坏的情况出现
  • 服务器载入 RDB 文件过程
    1. redis 服务器启动,在工作目录中查找是否有 RDB 文件,如果有则加载
    2. 检查文件开头的标识符
    3. 检查文件的 RDB 版号判断是否支持
    4. 根据文件中记录的设备附加信息,执行相应的操作和设置
    5. 检查数据库部分是否为空,若非空,则执行子操作:
      • a. 根据数据库号码,切换到正确数据库
      • b. 根据键值对总数量、带过期时间的键值对数量 创建数据库底层数据结构
      • c. 逐一读取并创建
    6. 如果服务器启用了复制功能,那么将之前缓存的lua脚本重新加载到缓存中
    7. 遇到EOF标识,确认 RDB 正文以及全部读取完毕
    8. 读取文件的CRC64校验和,与载入过程中计算的校验和对比,以此判断数据是否完整
  • RDB 持久化的缺陷
    • RDB 是一种全量持久化操作,它在创建的时候需要整个服务器包含的数据,这会消耗大量计算资源和内存资源,用户不太可能通过非常高的生成频率来保证数据安全
    • RDB 更像是一种数据备份手段

15.2 AOF 持久化

  • AOF 提供增量式的持久化功能
  • 服务器每次执行完写命令后,都会以协议文本的方式将被执行的命令追加到AOF文件的末尾
  • 只需要重新执行 AOF 文件中保存的redis 指令,就可以将数据库恢复
  • 在实际的 AOF 文件中,命令都是以 redis 网络协议的方式保存的

15.2.1 打开 AOF 持久化功能

  • appendonly yes 打开
  • appendonly no 关闭

15.2.2 设置 AOF 文件的冲洗频率

现代操作系统为了提高写入性能,通常会把多次硬盘写合并成一次,这种优化机制会对 AOF 持久化的安全性产生影响。

为了消除这种不确定性,redis提供了 appendfsync <value> 配置,<value>一共有三种选项: - always 每执行一个写命令,就 flush 一次 (最多丢失一条命令) - everysec 每隔 1s flush 一次 (默认值) - no 不主动对AOF 文件执行冲洗操作,由操作系统决定何时对AOF文件进行冲洗

15.2.3 AOF 重写

redis 服务器经过长期运行后,AOF 文件中将产生大量命令,可以通过重写的方式在减小文件体积的同时页满足逻辑一致。

redis 提供了 BGREWRITEAOF 这个异步命令重写 AOF 文件,fork 一个子进程进行重写

注意:

  • 如果用户发送BGREWRITEAOF命令时,服务器正在创建RDB文件,那么会等待RDB文件创建完成后再执行(避免同时写硬盘导致机器性能下降)
  • 如果执行BGREWRITEAOF命令的时候又接收到相同的命令,那么会返回rewriting already in progress 的错误

AOF 自动重写配置选项

  • auto-aof-rewrite-min-size
    • AOF 文件体积大于auto-aof-rewrite-min-size 将触发 AOF 重写
    • 默认 64mb
  • auto-aof-rewrite-percentage
    • 当前 AOF 文件的体积比上一次重写后的体积增加了auto-aof-rewrite-percentage后将触发重写

15.2.4 AOF 持久化的优缺点

  • 优点
    • 与 RDB 持久化可能丢失大量数据相比,AOF 持久化的安全性要高得多,通过使用everysec选项,可以将数据丢失的窗口限制在1s内
  • 缺点
    • AOF文件存储的是协议文本,会比包含相同逻辑数据、二进制格式的RDB文件要大得多,生成AOF文件所需要的时间也会比RDB方式更多
    • AOF文件恢复的方式是逐一执行redis命令,这使得数据恢复相比RDB慢很多
    • AOF重写使用的BGREWRITE与 RDB 使用的BGSAVE一样,fork 一个子进程,在数据库体积较大的情况下,都将占用大量的cpu和内存,导致服务器被短暂阻塞

15.3 RDB-AOF混合持久化

redis4.0 版本引入RDB-AOF混合持久化模式

打开服务器的AOF持久化功能,并且将aof-use-rdb-preamble <value> 选项置为yes, 那么服务器在执行AOF重写操作的时候,会像执行BGSAVE命令一样,根据数据库当前状态生成出相应的RDB数据,并且将这些数据写入到新建的AOF文件中。

重写开始后执行的redis命令,将以协议文本的方式追加到新AOF文件末尾。

RDB-AOF混合持久化

恢复流程: 恢复流程

既可以得到RDB文件恢复快的优点,又可以得到AOF文件将数据丢失的时间窗口限制在1s之内的有点

目前默认没有打开此功能

15.4 同时使用 RDB 持久化和 AOF 持久化

  • redis4.0后同时使用RDB持久化和AOF持久化已经不再必要
  • 优先使用RDB-AOF混合持久化

注意:

  • redis服务器启动时,会优先使用AOF文件进行数据恢复,只有在没有检测到 AOF 文件时,才考虑使用RDB文件进行数据恢复

15.5 无持久化

如果用户没有显式的开启持久化功能,那么redis服务器会默认使用以下配置进行RDB持久化:

1
2
3
save 60 10000
save 300 100
save 3600 1 

如果想完全关闭持久化功能,可以使用save ""取代,服务器将处于完全的无持久化状态中

15.6 SHUTDOWN 关闭服务器

当redis服务器接收到shutdown命令时,将执行:

  1. 停止处理客户端发送的命令请求
  2. 根据持久化配置,决定是否执行数据保存操作:
    1. 如果启用了RDB持久化,且数据库内容和RDB文件已经产生了差别,那么服务器将执行一次SAVE命令,用新的RDB文件覆盖。
    2. 如果启用了AOF持久化或者RDB-AOF混合持久化功能,那么它将冲洗AOF文件
    3. 如果都没有开启,那么将跳过
  3. redis服务器退出

可以显式的指定shutdown [save|nosave] 进行持久化操作: shutdown save

如果指定的是nosave选项,那么将不管持久化配置,直接关闭服务器,这可能丢失最后一次保存后的数据。