1. 是什么
- 在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里
- Redis默认是开启的
2. 工作原理
-
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失
3 配置
3.1 快照位置
- 默认生成的快照文件名为dump.rdb,通过设置dbfilename设置文件名
- 可以通过修改dir来配置存放路径
# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
# This makes the format more resistant to corruption but there is a performance
# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
# for maximum performances.
#
# RDB files created with checksum disabled have a checksum of zero that will
# tell the loading code to skip the check.
rdbchecksum yes
# The filename where to dump the DB,
dbfilename dump.rdb
# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir ./
3.2 同步策略
格式 save 秒数 写操作的次数
################################ SNAPSHOTTING ################################
#
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# In the example below the behaviour 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
#
# Note: you can disable saving completely by commenting out all "save" lines.
#
# It is also possible to remove all the previously configured save
# points by adding a save directive with a single empty string argument
# like in the following example:
#
# save ""
# 15分钟内改了1次
save 900 1
# 5分钟内改了10次
save 300 10
# 1分钟内改了10000次
save 60 10000
- 拿5分钟10次来说
4 触发条件
其实有分自动触发和手动触发:
-
手动触发:save/bgsave, 不建议
-
自动触发:满足redis配置文件中的自动触发条件(比如我们设置的:每5分钟有10次更新就会触发RDB文件生成)
-
自动触发:客户端关闭、关闭Redis服务时也会自动触发RDB
-
自动触发:执行flushall命令也会自动触发RDB
(个人感觉和word自动保存功能有相似的地方)
手动触发的区别:
- Redis提供了两个命令来实现RDB文件的生成,分别是save和bgsave
- 其中save命令为阻塞Redis服务器正常的进程,直到RDB文件创建结束为止,在此期间,Redis服务器不会处理任何请求,此时客户端发送的所有请求都会阻塞,知道服务器开始处理请求
- 而bgsave命令则会fork出一个子进程去创建RDB文件,父进程继续处理请求,不会影响Redis服务器处理正常的请求,但此时服务器会拒绝客户端发送的save和bgsave请求,避免重复执行生成和资源竞争
5 命令
-
stop-writes-on-bgsave-error
# However if you have setup your proper monitoring of the Redis server # and persistence, you may want to disable this feature so that Redis will # continue to work as usual even if there are problems with disk, # permissions, and so forth. stop-writes-on-bgsave-error yes
当Redis无法写入磁盘的话,直接关掉Redis的写操作。推荐yes
-
rdbcompression
# Compress string objects using LZF when dump .rdb databases? # For default that's set to 'yes' 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
- 对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩
- 如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能。推荐yes.
-
rdbchecksum
# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. # This makes the format more resistant to corruption but there is a performance # hit to pay (around 10%) when saving and loading RDB files, so you can disable it # for maximum performances. # # RDB files created with checksum disabled have a checksum of zero that will # tell the loading code to skip the check. rdbchecksum yes
在存储快照后,还可以让redis使用CRC64算法来进行数据校验,
但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能
6 备份和还原数据
- 题外话:假设我们每天都备份一下rdb文件(快照) -> 这个可以用shell脚本完成,命名就为: 日期_dump.rdb
开始备份操作:rdb会生成dump.rdb文件这个我们前面已经介绍了,
-
第一步,查看dump所在目录:在客户端执行该命令 config get dir
-
第二步,复制dump文件到我们的定义的文件夹,这里就相当于保留快照文件, 假设在根目录下创建了一个文件夹/snapshot/rdb
//我们先进入dump所在文件夹, 使用cp命令复制dump到我们定义好的文件夹 [root@iZbp1gy0nsh5vadm0h4sjjZ data]# ls appendonly.aof dump.rdb [root@iZbp1gy0nsh5vadm0h4sjjZ data]# cp dump.rdb 2022_5_26.rdb /snapshot/rdb/2022_5_26.rdb
上面就备份成功了,假设突然数据库突然大量的key丢失,或者被删除,我们还原之前快照点,那就开始还原:
-
第一步,我们需要停止redis服务 , 并删除dump.rdb文件(也不一定删除,可能mv到其他地方也行,但是这个文件夹只能有一个dump.rdb文件)
-
第二步,我们把之前备份的rdb文件,cp到当前文件夹下,并命名为dump.rdb
-
这里讲一下cp和mv,cp是复制的意思,mv是移动,移动的话相当于把文件移动过来,原来文件不在那个地方了, 我是感觉用cp合适一点
//用mv的话就这样, .代表移动到当前文件夹 [root@iZbp1gy0nsh5vadm0h4sjjZ data]# mv /snapshot/rdb/2022_5_26.rdb . //重命名, mv有移动和重命名2个功能 [root@iZbp1gy0nsh5vadm0h4sjjZ data]# mv 2022_5_26.rdb dump.rdb
-
-
第三步,重启redis服务
[root@iZbp1gy0nsh5vadm0h4sjjZ data]# docker stop xxx //我这里是直接删除了当前的dump.rdb文件了 [root@iZbp1gy0nsh5vadm0h4sjjZ data]# rm -rf dump.rdb //把备份文件复制过来,并命名为dump.rdb [root@iZbp1gy0nsh5vadm0h4sjjZ data]# cp /snapshot/rdb/2022_5_26.rdb dump.rdb //重启服务 [root@iZbp1gy0nsh5vadm0h4sjjZ data]# docker start xxx
7 注意点
- 我先清空了redis数据库,并设置了几个key,接下来我删除dump.rdb文件,客户端重新reload下,发现数据还在
- 因为redis的数据会缓存到内存中,所以删除dump.rdb文件后,数据依然会在
- 所以正确操作时,先停止redis服务 -> 删除dump.rdb文件 -> 启动redis服务, 这个也是还原数据时需要注意的点
- 我们知道rdb触发条件是比如 save 300 1 -> 5分钟,操作了2个key就快照一次,那这里就有2个点
- 操作key,添加肯定算,更新和删除算不算呢
- 实践证明,算
- 什么时候快照呢? 是5分钟内我操作了2个key,操作完第二个key的瞬间就快照,还是得5分钟末尾才会快照?
- 实践证明,5分钟末尾他才会统计并快照
- 操作key,添加肯定算,更新和删除算不算呢
8 优缺点
RDB优缺点:
- 优点:使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了
Redis
的高性能;而且RDB
文件存储的是压缩的二进制文件,适用于备份、全量复制,可用于灾难备份,同时RDB
文件的加载速度远超于AOF
文件。 - 缺点:
RDB
是间隔一段时间进行持久化,如果持久化之间的时间内发生故障,会出现数据丢失。所以这种方式更适合数据要求不严谨的时候,因为RDB
无法做到实时持久化,而且每次都要创建子进程,频繁创建成本过高- 前面我们也说了他说时间末尾才快照,并且操作的key要达到我们设定的key值, 假设我们设置1个小时 操作100个key我们快照
- 时间段正好是1.00 - 2.00, 1.30的时候我们需要还原数据,假设我们还原了1点的数据,那1.00-1.30的数据我们就还原不了了
- 更糟糕的是,假设0.00 - 1.00中间,操作的key没有达到我们设定的阈值, 那相当于我们只能拿更早的时间快照,所以数据完整性保证不了
- 前面我们也说了他说时间末尾才快照,并且操作的key要达到我们设定的key值, 假设我们设置1个小时 操作100个key我们快照
- 备份时占用内存,因为
Redis
在备份时会独立创建一个子进程,将数据写入到一个临时文件(需要的内存是原本的两倍); - 还有一点,
RDB
文件保存的二进制文件存在新老版本不兼容的问题