Redis RDB 持久化

Redis RDB 持久化

简介

RDB(Redis DataBase):RDB 持久性以指定的时间间隔执行数据集的时间点快照。

在指定的时间间隔,执行数据集的时间点快照。实现类似照片记录效果的方式,就是把某一时刻的数据和状态以文件的形式写到磁盘上,也就是快照。这样一来即使故障宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。这个快照文件就称为 RDB 文件(dump.rdb)。其中,RDB 就是 Redis DataBase 的缩写。

作用

  • 在指定的时间间隔内将内存中的数据集快照写入磁盘也就是行话讲 Snapshot 内存快照,它恢复时再将硬盘快照文件直接读回到内存里;
  • Redis 的数据都在内存中,保存备份时它执行的是全量快照,把内存中的所有数据都记录到磁盘中;
  • RDB 保存的是 dump.rdb 文件。

操作

配置文件

Redis6 以下

自动触发:在 Redis.conf 配置文件中的 SNAPSHOTTING 下配置 save 参数来触发 Redis 的 RDB 持久化条件,比如 save seconds changes:表示 seconds 秒内数据集存在 changes 次修改时,自动触发 bgsave 。

# In the example below the behavior will be to save:
# after 900 sec (15 min) if at least 1 key changed
# after 300 sec (5 min) if at least 10 keys changed
# after 60 sec if at least 10000 keys changed

save 900 1
save 300 10
save 60 10000

Redis6.2 以上

  • 时间触发:通过设置 save 配置项,可以指定多个时间间隔,当 Redis 距离上次执行 RDB 操作的时间超过设定的时间间隔时,Redis 就会自动执行一次 RDB 操作。例如,以下配置会在 Redis 距离上次执行 RDB 操作超过 900 秒,并且在此期间至少有一个键被修改时,自动执行 RDB 操作。

  • 修改触发:通过设置 save 配置项,可以指定多个修改次数的阈值,当 Redis 中的键被修改的次数超过设定的阈值时,Redis 就会自动执行一次 RDB 操作。例如,以下配置会在 Redis 中至少有 10000 个键被修改,并且距离上次执行 RDB 操作的时间超过 300 秒时,自动执行 RDB 操作。

# Unless specified otherwise, by default Redis will save the DB:
# After 3600 seconds (an hour) if at least 1 change save performed
# After 300 seconds (5 minutes) if at least 100 changes were performed
# After 60 seconds if at least 10000 changes were performed

save 3600 1 300 100 60 10000

注意

注:Redis7 较 Redis6 优化了时间触发策略:在 Redis7 中,Redis 引入了新的时间触发策略,称为动态时间模型。这个策略会根据 Redis 在内存中存储的键值对数量和占用的空间大小等动态因素来计算自动保存的时间间隔,使得自动保存的时间更加合理和高效。而在 Redis6 中,只有固定的时间触发策略。

操作步骤

自动触发

  • 通过修改 redis.conf 里配置的 save <seconds> <changes> 来修改保存配置;

  • 修改 dump 文件保存路径,修改配置文件 dir,进入 redis-cli 使用 CONFIG GET dir 查看文件保存路径。

  • 修改 dump 文件名称

  • 修改配置文件 dbfilename

  • 触发备份(具体见上面详解)—— 时间触发修改触发

  • 恢复方法

  • 将备份文件(dump.rdb)移动到 redis 安装目录并启动服务即可;

  • 执行 flushall/flushdb 命令也会产生 dump.rdb 文件(空文件);

注意:物理恢复,一定服务(redis-server)和备份(备份dump.rdb)分机隔离,不能放在同一台机器,必须分开各自存储,以防生产机器物理损坏后备份文件也挂了。

手动触发(save 和 bgsave)

save

在主程序中执行会阻塞当前 redis 服务器,直到持久化工作完成,执行 save 命令期间,Rdis 不能处理其他命令,线上静止使用

bgsave(默认)
  • Redis 会在后台异步进行快照操作,不阻塞快照同时还可以响应客户端请求,该触发方式会 fork(解释 fork:在Linux 程序中,fork() 会产生一个和父进程完全相同的子进程,但子进程在此后多会 exec 系统调用,出于效率考虑,尽量避免内存膨胀。)一个子进程,由子进程复制持久化过程。

    Redis 会使用 BGSAVE 对当前内存中的所有数据做快照,这个操作是子进程在后台完成的,这就允许主进程同时可以修改数据。

  • 可以通过 LASTSAVE 命令获取最后一次成功执行快照的时间。

    127.0.0.1:6379> LASTSAVE
    (integer) 1683797409
    127.0.0.1:6379> exit
    root@redis:/data# date -d @1683797409
    Thu May 11 17:30:09 CST 2023
    root@redis:/data# 

优势

官网介绍

  • RDB 是Redis 数据的一个非常紧凑的单文件时间点表示。RDB 文件非常适合备份。例如,您可能希望在最近的 24 小时内每小时归档一次 RDB 文件,并在 30天 内每天保存一个 RDB 快照。
  • 这使您可以在发生灾难时轻松恢复不同版本的数据集。RDB 非常适合灾难恢复,它是一个可以传输到远程数据中心或Amazon S3 (可能已加密)的压缩文件。
  • RDB 最大限度地提高了 Redis 的性能,因为 Redis 父进程为了持久化而需要做的唯一工作就是派生一个将完成所有其余工作的子进程。父进程永远不会执行磁盘 I/O 或类似操作。
  • 与AOF相比,RDB允许使用大数据集更快地重启
  • 在副本上,RDB 支持重启和故障转移后的部分重新同步

总结

  • 适合大规模的数据恢复;
  • 按照业务定时备份;
  • 对数据完整性和一致性要求不高;
  • RDB 文件在内存中的加载速度要比 AOF 快很多。

劣势

官网说明

  • 如果您需要在 Redis 停止工作时(例如断电后)将数据丢失的可能性降到最低,那么 RDB 并不好。您可以配置生成 RDB 的不同保存点(例如,在对数据集至少 5 分钟和 100 次写入之后,您可以有多个保存点)。但是,您通常会每五分钟或更长时间创建一次 RDB 快照,因此,如果 Redis 由于任何原因在没有正确关闭的情况下停止工作,您应该准备好丢失最新分钟的数据。
  • RDB 需要经常 fork() 以便使用子进程在磁盘上持久化。如果数据集很大,fork() 可能会很耗时,并且如果数据集很大并且 CPU 性能不是很好,可能会导致 Redis 停止为客户端服务几毫秒甚至一秒钟。AOF 也需要 fork() 但频率较低,您可以调整要重写日志的频率,而不需要对持久性进行任何权衡。

总结

  • 在一定间隔时间做一次备份,所以如果 redis 意外宕机的话,就会丢失从当前至最近一次快照期间的数据,快照之间的数据会丢失
  • 内存数据的全量同步,如果数据量太大会导致 I/O 严重影响服务器性能。
  • RDB 依赖于主进程的 fork,在更大的数据集中,这可能会导致服务请求的瞬间延迟。fork 的时候内存中的数据被克隆了一份,大致 2 倍的膨胀性。

数据丢失案例

假设数据备份的配置为 save 5 2 ;执行命令 set k1 v1set k2 v2 数据自动保存;执行命令 set k3 v3 后,断电服务终端(redis 未保存到 k3 数据);通电,redis 重新启动,数据丢失。

检查修复 dump.rdb 文件

redis-check-rdb dump.rdb

触发 RDB 快照的情况

  • 配置文件中默认的快照配置
  • 手动 save/bgsave 命令
  • 执行 flushall/flushdb 命令也会产生名为 dump.rdb 的空文件
  • 执行 shutdown 且没有设置开启 AOF 持久化
  • 主从复制时,主节点自动触发

禁用快照

  • 命令方式,动态所有停止 RDB 保存规则的方法:redis-cli config set save ""
  • 配置文件,快照禁用:注释掉所有 save 规则 save ""

RDB 优化配置项详解

配置文件 SNAPSHOTTING 模块

  • save <seconds> <changes>

  • dbfilename

  • dir

  • stop-writes-on-bgsave-error

    默认 yes,如果配置成 no,表示你不在乎数据不一致或者有其他的手段发现和控制这种不一致,那么在快照写入失败时,也能确保 redis 继续接受新的写请求。

  • rdbcompression

    默认 yes,对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis 会采用 LZF 算法进行压缩。如果你不想消耗 CPU 来进行压缩的话,可以设置为关闭此功能。

  • rdbchecksum

    默认 yes,在存储快照后,还可以让 redis 使用 CRC64 算法来进行数据校验,但是这样做会增加大约 10% 的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

  • rdb-del-sync-files

    在没有持久性的情况下删除复制中使用的 RDB 文件启用。默认情况下 no,此选项是禁用的。

总结

  • 优点

    • RDB 是一个非常紧凑的文件;

    • RDB 在保存 RDB 文件时父进程唯一需要做的就是 fork 出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他 IO 操作,所以 RDB 持久化方式可以最大化 redis 的性能;

    • 与 AOF 相比,在恢复大的数据集的时候,RDB 方式会更快一些;

  • 缺点

    • 数据丢失风险大;

    • RDB 需要经常 fork 子进程来保存数据集到硬盘上,当数据集比较大的时候,fork 的过程是非常耗时的,可能会导致 Redis 在一些毫秒级不能响应客户端请求。