Redis的持久化策略
# Redis的持久化策略
redis虽然是基于内存进行操作的一个数据库,但它也有将数据持久化到电脑磁盘上的能力
Redis的持久化有别于mysql这种数据库,它了实现⾼效的读写操作,并不会即时进⾏数据的持久化,⽽是按照⼀定的规则进⾏持久化操作的——持久化策略
Redis提供了2种持久化策略:
- RDB (Redis DataBase)
- AOF(Append Only File)
# RDB-持久化
RDB:在满⾜特定的redis操作条件时,将内存中的数据以数据快照的形式存储到rdb⽂件中。Redis重启的时候,通过加载dump.rdb文件来恢复数据,从而达到数据持久化。当然,你也可以通过手动触发的方式进行保存。
以下是手动触发rdb-持久化命令:
127.0.0.1:6379> save
OK
127.0.0.1:6379> bgsave
Background saving started
127.0.0.1:6379>
2
3
4
5
Save,是通过主进程来执行rdb,会阻塞所有命令。而bgsave,则会执行fork操作创建子进程,通过子进程来完成RDB持久化。阻塞只会发生在fork阶段。
# 原理
RDB是redis默认的持久化策略
,当redis中的写操作达到指定的次数、同时距离上⼀次持久化达到指定的时间 就会将redis内存中的数据⽣成数据快照,保存在指定的rdb⽂件中。
还需要注意的是,RDB每一次的数据快照
生成都是redis中的全部数据,且新的数据快照在保存到rdb文件时,会把原有的快照给覆盖。
其中的默认的规则的定义在redis.conf
配置文件中可以看到,我们也可以通过取消注释的方式并修改参数的方式进行自定义规则
# Unless specified otherwise, by default Redis will save the DB:
# * After 3600 seconds (an hour) if at least 1 change was performed
# * After 300 seconds (5 minutes) if at least 100 changes were performed
# * After 60 seconds if at least 10000 changes were performed
2
3
4
默认触发持久化条件:
- 3600s 1次:3600s内,至少有一个键发生变化,就会进⾏持久化
- 300s 10次:300s内,至少有一个键发生变化,就会进⾏持久化
- 60s 10000次:60s内,至少有一个键发生变化,就会就⾏持久化
此外,我们还可以指定rdb数据存储的文件,同样在配置文件中redis.conf
可以找到
# The filename where to dump the DB
dbfilename dump.rdb
2
最后,redis既然支持两种持久化策略,那么它们彼此肯定有类似开关的配置,来控制redis选择何种持久化策略
RDB持久化也是可以在配置文件中进行关闭的,将rdbcompression 后的yes改为no即可
# Compress string objects using LZF when dump .rdb databases?
# By default compression is enabled as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes
2
3
4
5
# 命令配置
除了通过配置文件方式改变,你也可以通过命令的方式进行修改
CONFIG SET dbfilename mydata.rdb
CONFIG SET dir /var/lib/redis/backup
2
第一条是修改持久化文件名称,第二条则是修改存储位置。
注意事项
- 重启服务:更改
dbfilename
和dir
需要重启 Redis 服务才能生效。 - 权限检查:确保目标目录具有足够的权限,Redis 服务账户能够写入该目录。
- 备份数据:在生产环境中进行此类更改前,请确保备份现有数据,以防意外丢失。
# RDB优缺点分析
缺点
- 如果redis出现故障,存在数据丢失的⻛险,丢失上⼀次持久化之后的操作数据
- RDB采⽤的是数据快照形式进⾏持久化,不适合实时性持久化;
- 如果数据量巨⼤,在RDB持久化过程中⽣成数据快照的⼦进程执⾏时间过⻓,会导致redis卡顿,因此 save时间周期设置不宜过短;
优点
- 但是在数据量较⼩的情况下,执⾏速度⽐较快;
- 由于RDB是以数据快照的形式进⾏保存的,我们可以通过拷⻉rdb⽂件轻松实现redis数据移植
# AOF-持久化
Append Only File,当达到设定触发条件时,将redis执⾏的写操作指令存储在aof⽂件中,从而达到数据持久化的目的。当Redis重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性。
那么这个触发条件是什么呢?系统定制的,还是说开发者自行配置的?
待交叉验证
肯定不能每执行一条写入命令就记录到文件中,那会严重拖垮Redis的性能。于是Redis准备了一个缓冲区,然后把要记录的命令先临时保存在这里,然后再择机写入文件。Redis把这个临时缓冲区叫做aof_buf。
但随着时间的推移,写的这个aof_buf备份文件越来越大,不仅非常占硬盘空间,复制、移动、加载、分析都非常的麻烦耗时。得想个办法把文件给压缩一下,于是有了AOF重写。那如何压缩呢——或者叫如何重写呢?
原来的一条条记录这种方式实在是太笨了,数据改来改去有很多中间状态都没用,何不就把最终的数据状态记录下来就好了。比如这三条指令可以合并成一条,不过这件事干起来还是很耗时间。于是Redis决定和RDB方式一样,fork出一个子,经常来做这件事情。
但这样还是存在一个问题,如果在重写期间,Redis要是修改了数据,就会出现和重写的内容不一致的情况。怎么办呢?
于是Redis在之前的aof_buf之外又准备了一个缓冲区AOF重写缓冲区(aof_rewrite_buf)。从子进程创建重写开始的那一刻起,Redis把后面来的写入命令也copy 1份,写到这个重写缓冲区中。等到子进程重写文件结束之后,再把这个缓冲区中的命令写入到新的lf文件中,最后再重命名新的文件,替换掉原来的那个臃肿不堪的大文件,终于重写大功告成。
以上就是系统默认的同步方式。
注意:Redis中默认未开启aof持久化。
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check https://redis.io/topics/persistence for more information.
appendonly no
2
3
4
5
6
7
# 原理
Redis将每⼀个成功的写操作
写⼊到aof⽂件中,当redis重启的时候就执⾏aof⽂件中的指令,并将其应用到内存中从而恢复数据。
跟rdb持久化类似,它的一些设置也可以在配置文件redis.conf
中进行修改:
将appendonly
设置为 yes,则表示开启aof持久化。
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check https://redis.io/topics/persistence for more information.
# 开启aof持久化策略
appendonly no
2
3
4
5
6
7
同样,我们也可以指定aof数据存储的文件
# The name of the append only file (default: "appendonly.aof")
## 设置 aof文件
appendfilename "appendonly.aof"
2
3
持久化策略同样可以在配置文件redis.conf
中找到并修改:
# If unsure, use "everysec".
# appendfsync always
appendfsync everysec
# appendfsync no
2
3
4
5
默认的触发条件是,每秒执行一次。另外2个分别是:
- appendfsync always:只要进⾏成功的写操作,就执⾏aof
- appendfsync no:让redis执⾏决定aof,完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不被推荐。
AOF(Append Only File)持久化机制并不是直接将写操作命令写入硬盘文件,而是首先写入一个缓冲区,然后再根据配置的
不同策略
将缓冲区的内容同步到硬盘文件中。这种设计是为了提高性能,避免频繁的磁盘 I/O 操作对性能的影响。
# AOF优缺点分析
aof存储的是指令,⽽且会对指令进⾏整理
;⽽RDB直接⽣成数据快照,在数据量不⼤时RDB⽐较快。
AOF策略记录每次对服务器进行写的操作,并将这些操作追加到文件末尾,以此来恢复原始数据。但是AOF文件有可能变得越来越大,为了降低存储开销和提高恢复速度,Redis提供了AOF重写功能。这个重写就是所谓的整理
。
它是Redis的一种优化措施,它通过对AOF文件中的指令进行整理(例如合并相同的指令、消除重复的指令等),从而达到减少文件大小的目的。具体来说,Redis在执行AOF重写时,会创建一个新的临时文件,然后遍历现有的AOF文件,并根据一系列规则对其进行整理,最后将整理后的指令写入新的临时文件中,然后再替换原有的AOF文件。这样就可以有效地减少AOF文件的大小,提高恢复速度。
比如有两个操作,分别是set k1为k2,set k1为 k3,整理后 就会合并为一个set k1为k3
优点
- aof是对指令⽂件进⾏增量更新,更适合实时性持久化
- 跟RDB类似,可以通过拷⻉aof⽂件进⾏redis数据移植
缺点
- 由于它会记录每一次写操作,因此会对服务器的性能造成一定的影响;
- 由于它以文件的形式存储数据,因此在文件较大时,会导致服务器读取速度变慢;
# 总结
粗略的讲,RDB是选择了性能,但数据容易丢失,而AOF选择了保存数据,性能上不如RDB。
redis官⽅建议同时开启2中持久化策略,但如果同时存在aof⽂件和rdb⽂件的情况下恢复数据时,只会选择aof文件。
# 断电-恢复
当 Redis 重启时,会根据以下逻辑决定如何恢复数据:
- 检查 AOF 文件:如果 AOF 持久化被启用(即
appendonly yes
),Redis 会首先尝试使用 AOF 文件恢复数据。如果 AOF 文件存在并且是有效的,Redis 将从 AOF 文件中恢复数据。 - 检查 RDB 文件:如果 AOF 文件不存在或无法使用,Redis 会检查是否存在 RDB 文件。如果存在有效 RDB 文件,Redis 将从 RDB 文件中恢复数据。
- 恢复顺序:
- 优先使用 AOF:如果 AOF 文件存在并且可用,Redis 会优先使用 AOF 文件进行恢复。
- 使用 RDB 作为备选:如果 AOF 文件不存在或无法使用,Redis 会尝试使用 RDB 文件恢复数据。
# 扩展
最后,在Redis4.0
之后,还提供了混合模式
,这种模式下RDB持久化的数据也会写进 appendonly.aof文件,而不是 dump.rdb 文件;而AOF持久化的命令也追加在 appendonly.aof 中RDB持久化的数据之后
也就是说,混合模式下 appendonly.aof 文件的前部分是 RDB的数据,后部分才是AOF的数据。
对应的开启同样也在配置文件redis.conf,但开启混合不仅需要开启混合开关,还需开启aof的持久化开关
# 开启aof持久化策略
appendonly no
# When loading, Redis recognizes that the AOF file starts with the "REDIS"
# string and loads the prefixed RDB file, then continues loading the AOF
# tail.
aof-use-rdb-preamble yes
2
3
4
5
6
这样掉电恢复时,就变成了如下步骤:
- 首先读取 AOF 文件中的 RDB 部分,将其中的键值对加载到内存中
- 然后读取 AOF 文件中的 AOF 部分,按顺序执行其中的命令,更新内存中的数据