Redis是一个基于内存的数据库,所以他的数据存储在内存中,但是为了避免突然宕机而导致数据全部丢失,因此必须有一种机制来保证 Redis 的数据不会因为故障而丢失,这种机制就是 Redis 的持久化机制。
Redis有两种持久化的方式,快照(RDB文件)和追加式文件(AOF文件)
RDB(Redis DataBase)
是什么
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。
备份是如何执行的
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能,如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
为什么不直接把数据同步到临时文件中而选择同步到一个临时文件区域?
如果直接同步到文件中:假设现在有10个key,当同步到第8个key的时候,突然服务器挂掉,就造成了数据的不完整,所以要先同步到临时文件中,等同步完成,再替换rdb的文件,这样做保证了数据的一致性、完整性、安全性。这个过程叫做写时复制技术,rdb的底层就是这么做到的
Fork
fork 的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。 子进程读取数据,然后序列化写到磁盘中。rdb 默认保存的是dump.rdb文件
dump.rdb文件
在redis.conf中配置文件名称,默认为dump.rdb
文件放到启动目录中
stop-writes-on-bgsave-error yes:当redis无法写入磁盘,直接关掉redis的写操作
rdbcompression yes:压缩文件
rdbchecksum yes:检查数据我完整性,大约10%性能消耗
触发RDB快照
save时只管保存,其他不管,全部阻塞,手动保存,不建议
bgsave:redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。
执行flushall命令,也会产生dump.rdb文件,但里面是空的,无意义
你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。
你也可以通过调用save或bgsave, 手动让 Redis 进行数据集保存操作。
比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集
save 60 1000
这种持久化方式被称为快照(snapshot)。
快照的运作方式
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
-
Redis 调用 fork() ,产生一个子进程,此时同时拥有父进程和子进程。
-
子进程将数据集写入到一个临时 RDB 文件中。
-
当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。
如何恢复
将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可(CONFIG GET dir获取目录)
如何停止
动态停止RDB保存规则的方法:redis-cli config set save ""
优势
-
适合大规模的数据恢复
-
对数据完整性和一致性要求不高更适合用
-
节省磁盘空间
-
恢复速度快
劣势
-
如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失(丢失最后一次快照后的所有修改)。
-
由于RDB是通过fork子进程来协助完成数据持久化工作的,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。
-
虽然redis在fork时采用了写时复制技术,但如果数据庞大时还是比较消耗性能
总结
-
RDB是一个非常紧凑的文件
-
RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能
-
与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些
-
数据丢失风险大
-
RDB需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致redis在一些毫秒级不能响应客户端的请求