28redis持久化之理论介绍
redis持久化:redis如何将内存数据写入磁盘中
为什么需要持久化?
内存数据一断电就会消失,那么所有的请求都会打到数据库中。因此让redis中的数据长期持有,不管是重启、故障、恢复、宕机,还是能从磁盘上读回曾经保存的数据。
一般redis持久化指的是RDB[Redis Database] 和 AOF[Append Only File]。可以选择其中一种,也可以两种都使用,将内存数据写入磁盘中。
- persistent snapshot【RDB】:快照,将数据打包生成rdb文件。用于整体恢复。
- Append Only File【AOF】:将所有写命令的操作都记录下来。恢复时挨个挨个重新运行一次。
29 redis持久化之RDB简介
RDB(Redis数据库):RDB持久性以指定的时间间隔执行数据集的时间点快照。
实现类似照片记录效果的方式,就是把某一时刻的数据和状态以文件的形式写到磁盘上,也就是
快照。这样一来即使故障宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。
这个快照文件就称为RDB文件(dump.rdb),其中,RDB就是Redis DataBase的缩写。
如果服务器挂了,redis缓存数据在重启的时候将会通过硬盘里存储的rgb文件加载回来。
作用:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot内存快照,它恢复时再将硬盘快照文件直接读回到内存里
一锅端:Redis的数据都在内存中,保存备份时它执行的是全量快照,也就是说,把内存中的所有数据都记录到磁盘中,一锅端
Rdb保存的是dump.rdb文件
redis6版本的redis.conf文件中找到snapshotting ,主要用来设置redis中的rdb。
######## 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 behavior will be to save: //发生以下行为将会保存
after 900 sec (15 min) if at least 1 key changed // 15分钟内有1次修改
after 300 sec (5 min) if at least 10 keys changed // 5分钟内有10此修改
after 60 sec if at least 10000 keys changed // 1分钟内有1万次修改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 ""
save 900 1
save 300 10
save 60 10000
总结:
Redis6.0.16以下
自动触发:
在 Redie.conf 配置文件中的 SNAPSHOTTING 下配置 save 参数,来触发Redis的 RDB持久化条件,
比如“save m n”:表示m秒内数据集存在 n 次修改时,自动触发 bgsave
save 900 1:每隔 900s(15min),如果有超过1个key 发生了变化,就写一份新的 RDB 文件
save 300 10:每隔 300s(5min),如果有超过10个key 发生了变化,就写一份新的 RDB 文件
save 60 10000:每隔 60s(1min),如果有超过 10000个key发生了变化,就写一份新的RDB文件
redis7
除非另有指定,Redis 默认会在以下情况下保存数据库(持久化):
-
在 3600 秒(1 小时)后,如果至少执行了 1 次修改
-
在 300 秒(5 分钟)后,如果至少执行了 100 次修改
-
在 60 秒后,如果至少执行了 10000 次修改
30 redis持久化之RDB配置说明
网站说明:
默认情况下,Redis 会将数据集的快照保存到磁盘上的一个名为 dump.rdb
的二进制文件中。
你可以配置 Redis:当在 N 秒内数据集发生了至少 M 次修改时,就自动保存一次数据集,或者你也可以手动调用 SAVE 或 BGSAVE 命令来执行保存操作。
案例5秒2次修改
vim redis7.conf
linux常用快捷键:
复制:Ctrl + Shift + C
粘贴:Ctrl + Shift + V
保存并退出:esc :wq
保存不退出:esc :w
修改文件:i 在当前光标前插入
vim中查找:
输入
/关键词
然后回车 → 向下查找输入
?关键词
然后回车 → 向上查找按
n
→ 查找下一个匹配按
N
→ 查找上一个匹配
我没有修改路径,所以进入redis.conf还是按照默认的路径
cd /usr/local/src/redis路径
vim redis.conf
save 5 2
修改dump文件保存路径
修改dump文件名称
修改后重启一下配置文件
redis-server redis.conf的文件路径
操作时的tips: 刚开始配置并没有成功,但路径下出现了log文件。检查后发现是reids端口被占用导致配置失败。因此重启配置文件的时候一定要关闭目前的redis进程。【sudo systemctl stop redis 停止已有的 Redis 实例或其他占用该端口的程序】。
31 redis持久化之RDB自动触发
save 5 2的含义是在5s秒修改两次就进行快照。如图,5s内更改一次并不会更新rdb文件。
如何恢复
将备份文件(dump.rdb)移动到redis安装目录并启动服务即可。备份成功后故意用flushdb清空redis,看看是否可以恢复数据
物理恢复,一定服务和备份分机隔离
把当前目录下的 dump6379.rdb
文件 重命名 为 dump6379.rdb.bak
mv dump6379.rdb dump6379.rdb.bak
在redis中清掉当前数据
FLUSHDB
此时再检查 /myredis/dumpfiles目录
因为当我们使用一个提交命令,类似于终止命令时,redis为了保证事物的一致性,也会自动生成rdb文件。
重启一下配置文件
redis-server redis.conf的文件路径
再次连接redis服务器后运行keys* 发现redis数据库为空
因为重新连接时,redis加载的是新生成的rdb文件。而此文件提交时清空了数据库,因此加载后数据库也为空。
结论:执行flushall/flushdb命令也会产生dump.rdb文件,但里面是空的,无意义
快捷键 退出redis:输入quit ,exit或按ctrl+D
物理恢复
首先强制删除掉/myredis/dumpfiles中的dump6379.rdb文件
rm -f dump6379.rdb
SHUTDOWN // 退出
// 发现/myredis/dumpfiles中又生成了dump6379.rdb文件
SHUTDOWN :
-
SHUTDOWN
是 Redis 的内置命令,会优雅地关闭 Redis 服务。 -
它会将内存中的数据持久化到
dump.rdb
(如果配置了 RDB),然后关闭服务。
再次清除掉/myredis/dumpfiles中的dump6379.rdb文件
把当前目录下的 dump6379.rdb.bak
文件 重命名 为 dump6379.rdb
此时再重新启动配置文件,数据库恢复。
备注:不可以把备份文件dump.rdb和生产redis服务器放在同一台机器,必须分开各自存储
以防生产机物理损坏后备份文件也挂了。
32 redis持久化之RDB手动触发
为什么要手动触发?假如我们存储了很重要的数据,那么手动立刻保存更加保险。
redis提供了两个命令来生成RDB文件,分别是save和bgsave
工作原理(How it works)
每当 Redis 需要将数据集保存到磁盘时,会执行以下操作:
-
Redis 会进行一次 fork 操作(派生一个新进程)。此时会有一个 子进程 和一个 父进程。
-
子进程并不影响出进程的运行,开始将数据集写入一个 临时的 RDB 文件。
-
当子进程完成新 RDB 文件的写入后,它会 替换旧的 RDB 文件。
这种方式使 Redis 能够利用操作系统的 写时复制(copy-on-write)机制 来提高效率。
save【一般不适用】
在主程序中执行会阻塞当前redis服务器,直到持久化工作完成。执行save命令期间,Redis不能处理其他命令【包括缓存服务器对外提供服务的功能,若redis数据量很大,则save的过程会严重阻碍其他进程的运行】,线上禁止使用
bgsave
Redis会在后台异步进行快照操作,不阻塞快照同时还可以响应客户端请求,该触发方式会fork一个子进程由子进程复制持久化过程。
Redis会使用bgsave对当前内存中的所有数据做快照,这个操作是子进程在后台完成的,这就允许主进程同时可以修改数据。
fork是什么?:程序【父进程】运行到 fork()
时,会从当前进程中“克隆”出一个一模一样的新进程【子进程】,两者并行运行。
LASTSAVE
可以通过lastsave命令获取最后一次成功执行快照的时间