Redis 持久化技术
1. RDB
1.1 RDB 基本介绍
RDB 是什么:在指定的时间间隔内将内存中的数据集快照写入磁盘
(1) 备份是如何被执行的
Redis 会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。
整个过程中,主进程是不进行任何 IO 操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。
RDB 的缺点:最后一次持久化后的数据可能丢失。
(2)fork
- fork 的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
- 在 Linux 程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会 exec 系统调用,出于效率考虑,Linux 中引入了**“写时复制技术”**
- 一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。
1.2 RDB 持久化流程
1.2.dump.rdb 文件
在 redis.conf 中配置文件名称,默认为 dump.rdb
1.2.1 配置位置
rdb 文件的保存路径,默认在 Redis 启动命令行所在的目录下
1.2.2 如何触发 RDB 快照
配置文件中默认的快照配置
save
命令 VSbgsave
命令:
save
:只管保存,全部阻塞,手动保存
bgsave
:redis 会在后台异步执行快照操作,快照同时可以响应客户端请求,
可以通过 lastsave
命令获取最后一次成功执行快照的时间
-
flushall
命令:产生 dump.rdb 空文件,无意义 -
stop-writes-on-bgsave-error
:当 Redis 无法写入磁盘的话,直接关掉 Redis 的写操作。推荐 yes. -
rdbcompression
:
对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis 会采用 LZF 算法进行压缩。
如果你不想消耗 CPU 来进行压缩的话,可以设置为关闭此功能。推荐 yes -
rdbchecksum
:检查完整性,推荐 yes.
在存储快照后,还可以让 redis 使用 CRC64 算法来进行数据校验,
但是这样做会增加大约 10% 的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能
1.2.3 RDB 备份
先通过 config get dir 查询 rdb 文件的目录
将*.rdb 的文件拷贝到别的地方
rdb 的恢复步骤:
-
关闭 Redis
-
先把备份的文件拷贝到工作目录下 cp dump2.rdb dump.rdb
-
启动 Redis, 备份数据会直接加载
1.3 RDB 的优点
- 适合大规模的数据恢复
- 对数据完整性和一致性要求不高更适合使用
- 节省磁盘空间
- 恢复速度快
1.4 RDB 的劣势
- Fork 的时候,内存中的数据被克隆了一份,大致 2 倍的膨胀性需要考虑
- 虽然 Redis 在 fork 时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能。
- 在备份周期在一定间隔时间做一次备份,所以如果 Redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改。
1.5 总结
2. AOF(Append Only File)
2.1 基本介绍
以日志的形式来记录每个写操作(增量操作),将 Redis 执行过得所有写指令记录下(不记录读操作),
只许追加文件但不可以改写文件。redis 启动时会读取该文件来重新构建数据,换言之,redis 重启根据日志文件
的内容将执行写指令来完成数据的恢复工作。
AOF 默认不开启:在 redis.conf 中配置文件名称,默认为 append.aof,AOF 文件的保存路径与 RDB 的路径一致
AOF 和 RDB 同时开启:系统默认取 AOF 的数据(数据不会存在丢失)
2.2 AOF 持久化流程
(1)客户端的请求写命令会被 append 到 AOF 缓存区内
(2) AOF 缓存区根据 AOF 持久化策略[always, everysec, no]将操作 sync 到磁盘的 AOF 文件中
(3)AOF 文件大小超过重写策略或手动重写时,会对 AOF 文件 rewrite,压缩 AOF 文件容量
(4)Redis 服务重启时,会重新 load AOF 文件中的写操作来恢复数据
2.3 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,然后重新加载
2.4 AOF 同步评率
appendfsync always
:始终同步,每次 Redis 的写入都会立刻计入日志,性能较差但数据完整性较好
appendfsync everysec
:每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失
appendfsync no
:redis 不主动进行同步,把同步时机交给操作系统
2.5 Rewrite 压缩
2.5.1 什么是 Rewrite:
AOF 采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,
当 AOF 文件的大小超过所设定的阈值时,Redis 就会启动 AOF 文件的内容压缩,
只保留可以恢复数据的最小指令集,可以使用命令 bgrewriteaof
2.5.2 重写原理,如何实现重写
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% 时开始重写
(文件是原来重写后文件的2倍时触发)
auto-aof-rewrite-min-size
:设置重写的基准值,最小文件 64MB。达到这个值开始重写。
例如:文件达到70MB开始重写,降到50MB,下次什么时候开始重写?100MB
系统载入时或者上次重写完毕时,Redis 会记录此时 AOF 大小,设为 base_size,
如果 Redis 的 AOF 当前大小 >= base_size +base_size*100% (默认)且当前大小 >=64mb(默认)的情况下,Redis
会对 AOF 进行重写。
2.5.3 重写流程
(1)bgrewriteaof 触发重写,判断是否当前有 bgsave 或 bgrewriteaof 在运行,如果有,则等待该命令结束后
再继续执行。
(2)主进程 fork 出子进程执行重写操作,保证主进程不会阻塞。
(3)子进程遍历 redis 内存中数据到临时文件,客户端的写请求同时写入 aof_buf 缓冲区和 aof_rewrite_buf,
重写缓冲区保证原 AOF 文件完整以及新 AOF 文件生成期间的新的数据修改动作不会丢失。
(4)子进程写完新的 AOF 文件后,向主进程发信号,父进程更新统计信息。
主进程把aof_rewrite_buf中的数据写入到新的AOF文件。
(5)使用新的 AOF 文件覆盖旧的 AOF 文件,完成 AOF 重写。
2.6 AOF 的优势
- 备份机制稳健,丢失数据概率更低
- 可读的日志文件,通过操作 AOF 稳健,可以处理误操作
2.7AOF 的劣势
- 比起 RDB 占用更多的磁盘空间。
- 恢复备份速度要慢。
- 每次读写都同步的话,有一定的性能压力。
- 存在个别 Bug,造成恢复异常
2.8 总结
3. RDB 与 AOF 的对比
3.1 选择建议
官方推荐两个都启用。
如果对数据不敏感,可以选单独用 RDB。
不建议单独用 AOF,因为可能会出现 Bug。
如果只是做纯内存缓存,可以都不用。
3.2 两者对比
(1)基本信息
-
RDB 持久化方式能够在指定的时间间隔能对你的数据进行快照存储
-
AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数
据,AOF 命令以 redis 协议追加保存每次写的操作到文件末尾.
-
Redis 还能对 AOF 文件进行后台重写,以缩小使得 AOF 文件的体积
(2)只做缓存
如果只希望数据在服务器运行的时候存在,也可以不使用任何持久化方式.
(3)同时开启 RDB 和 AOF
-
在这种情况下,当 redis 重启的时候会优先载入 AOF 文件来恢复原始的数据, 因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整.
-
RDB 的数据不实时,同时使用两者时服务器重启也只会找 AOF 文件。
(4)只使用 AOF?
- 不建议,因为 RDB 更适合用于备份数据库(AOF 在不断变化不好备份), RDB 可以快速重启,而且不会有 AOF 可能潜在的 bug。
3.3 性能建议
因为 RDB 文件只用作后备用途,建议只在 Slave 上持久化 RDB 文件,而且只要 15 分钟备份一次就够了,只保留 save 9001 这条规则。
如果使用 AOF,
- 好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只 load 自己的 AOF 文件就可以了。
- 代价,一是带来了持续的 IO,二是 AOF 将 rewrite 过程中产生的新数据写到新文件会造成阻塞
只要硬盘许可,尽量减少 AOF rewrite 的频率,AOF 重写的基础大小默认值 64M 太小了,可以设到 5G 以上。
默认超过原大小 100% 大小时重写可以改到适当的数值。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于