笔记整理自【尚硅谷】Redis 6 入门到精通 超详细 教程
Redis——持久化操作(RDB、AOF)
1. RDB(Redis DataBase)
概述
RDB是什么
- 在指定的时间间隔内将内存中的数据集快照写入磁盘, 即 Snapshot 快照,恢复时是将快照文件直接读到内存里。
备份是如何执行的
- Redis 会单独创建一个子进程(fork)来进行持久化
- 会先将数据写入到一个临时文件中,待持久化过程完成后,再将这个临时文件替换上次持久化好的文件(内容覆盖到 dump.rdb)。
- 整个过程中,主进程是不进行任何 IO 操作的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。
- RDB 的缺点是最后一次持久化后的数据可能丢失。
Fork
-
作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
-
在 Linux 程序中,fork() 会产生一个和父进程完全相同的子进程,但子进程在此后多会 exec 系统调用,出于效率考虑,Linux 中引入了 “写时复制技术”
-
一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程
RDB持久化流程
redis.conf
-
dump 文件名字
-
在 redis.conf 中配置文件名称,默认为 dump.rdb。
-
-
dump 保存位置
-
rdb 文件的保存路径可以修改。默认为 Redis 启动时命令行所在的目录下。
-
-
stop-writes-on-bgsave-error
-
当 redis 无法写入磁盘,直接关闭 redis 的写操作。推荐 yes。
-
-
rdbcompression 压缩文件
-
对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis 会采用 LZF 算法 进行压缩。
-
如果你不想消耗 CPU 来进行压缩的话,可以设置为关闭此功能。推荐 yes。
-
-
rdbchecksum 检查完整性
-
在存储快照后,还可以让 redis 使用 CRC64 算法 来进行数据校验。
- 即检查数据是否完整、是否有损坏。
-
但是这样做会增加大约 10 % 10\% 10% 的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。推荐 yes。
-
save VS bgsave
RDB 持久化主要是通过save
和bgsave
两个命令对Redis数据库中当前的数据做snapshot(快照)
并生成 rdb 文件来实现的。在 Redis 启动的时候会检测 rdb 文件,然后载入 rdb 文件中未过期的数据到服务器中。
save
时只管保存,其它不管,全部阻塞。手动保存。bgsave
是非阻塞的,通过 fork 了一个子进程来完成的。
save 和 bgsave 的区别
- save:直接调用
rdbSave
函数 ,阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。 - bgsave:Redis 会在后台异步进行快照操作,快照同时还可以响应客户端请求。
- fork 出一个子进程,子进程负责调用
rdbSave
函数,并在保存完成之后向主进程发送信号,通知保存已完成。 - Redis 服务器在
bgsave
执行期间仍然可以继续处理客户端的请求。
- fork 出一个子进程,子进程负责调用
RDB 可以通过向服务器提供配置信息来自动间隔性保存。如默认情况下服务器满足以下 3 3 3 个条件中任意一个条件就会触发 bgsave 命令:
格式:
save 秒钟 写操作次数
save 900 1 // 服务器在900s(15min)之内,对数据库进行了至少1次修改
save 300 10 // 服务器在300s(5min)之内,对数据库进行了至少10次修改
save 60 10000 // 服务器在60s(1min)之内,对数据库进行了至少10000次修改
RDB 是整个内存的压缩过的 Snapshot,RDB 的数据结构,可以配置复合的快照触发条件。
默认是 1 1 1 分钟内改了 10000 10000 10000 次,或 5 5 5 分钟内改了 10 10 10 次,或 15 15 15 分钟内改了 1 1 1 次。
这种持久化方式被称为快照 snapshotting。
-
禁用
-
不设置 save 指令,或者给 save 传入空字符串
-
动态停止 RDB:
redis-cli config set save ""
# save后给空值,表示禁用保存策略
-
可以通过lastsave
命令获取最后一次成功执行快照的时间。
执行flushall
命令,也会产生dump.rdb
文件,但里面是空的,无意义。
rdb的备份
-
先通过
config get dir
:查询 rdb 文件的目录 -
将
*.rdb
的文件拷贝到别的地方cp dump.rdb dump2.rdb
-
rdb 的恢复
- 关闭 Redis
- 先把备份的文件拷贝到工作目录下:
cp dump2.rdb dump.rdb
- 启动 Redis, 备份数据会直接加载
优点
- 适合大规模的数据恢复;
- 对数据完整性和一致性要求不高更适合使用;
- 节省磁盘空间;
- 恢复速度快。
缺点
- Fork 的时候,内存中的数据被克隆了一份,大致 2 2 2 倍的膨胀性需要考虑。
- 虽然 Redis 在 fork 时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能。
- 在备份周期在一定间隔时间做一次备份,所以如果 Redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改。
小总结
2. AOF(Append Only File)
概述
以日志的形式来记录每个写操作(增量保存),将 Redis 执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,Redis 启动之初会读取该文件重新构建数据,换言之,如果 Redis 重启就会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
AOF 持久化流程
-
客户端的请求写命令会被 append 追加到 AOF 缓冲区内;
-
AOF 缓冲区根据 AOF 持久化策略
[always,everysec,no]
将操作 sync 同步到磁盘的 AOF 文件中; -
AOF 文件大小超过重写策略或手动重写时,会对 AOF 文件 Rewrite 重写,压缩 AOF 文件容量;
-
Redis 服务重启时,会重新 load 加载 AOF 文件中的写操作达到数据恢复的目的。
AOF 和 RDB 同时开启时,系统默认读取 AOF 的数据(数据不会存在丢失)。
配置
-
AOF 默认不开启
- 此时我们将 AOF 开启,改为 yes。
-
文件名字
- 可以在
redis.conf
中配置文件名称,默认为appendonly.aof
- AOF 文件的保存路径,同 RDB 的路径一致。
- 可以在
-
AOF 启动/修复/恢复
AOF 的备份机制和性能虽然和 RDB 不同,但是备份和恢复的操作同 RDB 一样,都是拷贝备份文件,需要恢复时再拷贝到 Redis 工作目录下,启动系统即加载。
- 正常恢复
- 修改默认的 appendonly no,改为 yes
- 将有数据的 aof 文件复制一份保存到对应目录(查看目录:config get dir)
- 恢复:重启 redis 然后重新加载
- 异常恢复
- 修改默认的 appendonly no,改为 yes
- 如遇到 AOF 文件损坏,通过
/usr/local/bin/redis-check-aof--fix appendonly.aof
进行恢复 - 备份被写坏的 AOF 文件
- 恢复:重启 redis,然后重新加载
- 正常恢复
-
AOF 同步频率设置
- appendfsync always
- 始终同步,每次 Redis 的写入都会立刻记入日志;
- 性能较差但数据完整性比较好。
- appendfsync everysec(推荐 并且也是默认)
- 每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
- 这种策略可以兼顾速度和安全性。
- appendfsync no
- Redis 不主动进行同步,把同步时机交给操作系统。
- appendfsync always
Rewrite 重写压缩
-
AOF 采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当 AOF 文件的大小超过所设定的阈值时,Redis 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。
-
执行命令 bgrewriteaof,Redis 会将 AOF 文件的内容压缩,生成一个新的 AOF 文件,只保留可以恢复数据的最小指令集。
- Redis2.2 需要自己手动执行 bgrewriteaof 命令;Redis2.4 则可以自动触发 AOF 重写
set k1 v1 set k2 v2 ↓ set k1 v1 k2 v2
重写原理,如何实现重写
- AOF 文件持续增长而过大时,会 fork 出一条新进程来将文件重写(也是先写临时文件最后再 rename),redis4.0版本后的重写,是指就是把 rdb 的快照,以二级制的形式附在新的 aof 头部,作为已有的历史数据,替换掉原来的流水账操作。
no-appendfsync-on-rewrite:
- 如果 no-appendfsync-on-rewrite=
yes
,不写入 aof 文件只写入缓存,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的缓存数据。(降低数据安全性,提高性能) - 如果 no-appendfsync-on-rewrite=
no
, 还是会把数据往磁盘里刷,但是遇到重写操作,可能会发生阻塞。(数据安全,但是性能降低)
触发机制,何时重写
- Redis 会记录上次重写时的 AOF 大小,默认配置是当 AOF 文件大小是上次 rewrite 后大小的一倍且文件大于 64M 时触发
- 重写虽然可以节约大量磁盘空间,减少恢复时间。但是每次重写还是有一定的负担的,因此设定 Redis 要满足一定条件才会进行重写。
- auto-aof-rewrite-percentage:设置重写的基准值,文件达到 100 % 100\% 100% 时开始重写(文件是原来重写后文件的 2 2 2 倍时触发)
- auto-aof-rewrite-min-size:设置重写的基准值,最小文件 64MB。达到这个值开始重写。
- 例如:文件达到 70MB 开始重写,降到 50MB,下次什么时候开始重写?100MB
- 系统载入时或者上次重写完毕时,Redis 会记录此时 AOF 大小,设为 base_size
- 如果 Redis 的 AOF 当前大小 >= base_size + base_size×100%(默认)且 当前大小 >=64mb(默认)的情况下,Redis 会对 AOF 进行重写。
重写流程
- bgrewriteaof 触发重写,判断是否当前有 bgsave 或 bgrewriteaof 在运行,如果有,则等待该命令结束后再继续执行。
- 主进程 fork 出子进程执行重写操作,保证主进程不会阻塞。
- 子进程遍历 redis 内存中数据到临时文件,客户端的写请求同时写入 aof_buf 缓冲区和 aof_rewrite_buf 重写缓冲区保证原 AOF 文件完整以及新 AOF 文件生成期间的新的数据修改动作不会丢失。
- 子进程写完新的 AOF 文件后,向主进程发信号,父进程更新统计信息。
- 主进程把 aof_rewrite_buf 中的数据写入到新的 AOF 文件。
- 使用新的 AOF文件覆盖旧的 AOF 文件,完成 AOF 重写。
优点
- 备份机制更稳健,丢失数据概率更低;
- 可读的日志文本,通过操作 AOF 稳健,可以处理误操作。
缺点
- 比起 RDB 占用更多的磁盘空间;
- 恢复备份速度要慢;
- 每次读写都同步的话,有一定的性能压力;
- 存在个别 Bug,造成不能恢复。
小总结
3. 总结
Ⅰ. 用哪个好
- 官方推荐两个都启用。
- 如果对数据不敏感,可以选单独用 RDB。
- 不建议单独用 AOF,因为可能会出现 Bug。
- 如果只是做纯内存缓存,可以都不用。
Ⅱ. 官网建议
- RDB 持久化方式能够在指定的时间间隔能对你的数据进行快照存储
- AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据, AOF 命令以 redis 协议追加保存每次写的操作到文件末尾
- Redis 还能对 AOF 文件进行后台重写,使得 AOF 文件的体积不至于过大
- 只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
- 同时开启两种持久化方式
- 在这种情况下,当 redis 重启的时候会优先载入 AOF 文件来恢复原始的数据,因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整
- RDB 的数据不实时,同时使用两者时服务器重启也只会找 AOF 文件。那要不要只使用 AOF 呢?
- 建议不要,因为 RDB 更适合用于备份数据库(AOF 在不断变化不好备份),快速重启,而且不会有 AOF 可能潜在的 bug,留着作为一个万一的手段。
- 性能建议
- 因为 RDB 文件只用作后备用途,建议只在 Slave 上持久化 RDB 文件,而且只要
15
15
15 分钟备份一次就够了,只保留
save 900 1
这条规则。 - 如果使用 AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只 load 自己的 AOF 文件就可以了。
- 代价,一是带来了持续的 IO,二是 AOF rewrite 的最后将 rewrite 过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。
- 只要硬盘许可,应该尽量减少 AOF rewrite 的频率,AOF 重写的基础大小默认值 64M 太小了,可以设到 5G 以上。
- 默认超过原大小
100
%
100\%
100% 大小时重写可以改到适当的数值。
文件就可以了。 - 代价,一是带来了持续的 IO,二是 AOF rewrite 的最后将 rewrite 过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。
- 只要硬盘许可,应该尽量减少 AOF rewrite 的频率,AOF 重写的基础大小默认值 64M 太小了,可以设到 5G 以上。
- 默认超过原大小 100 % 100\% 100% 大小时重写可以改到适当的数值。
- 因为 RDB 文件只用作后备用途,建议只在 Slave 上持久化 RDB 文件,而且只要
15
15
15 分钟备份一次就够了,只保留