什么是RDB(redis database)?
在指定的时间间隔内,将内存中的数据写入磁盘,恢复时,将快照文件读入内存中
RDB默认开启方式
RDB 将数据库的快照(snapshot)以二进制的方式保存到磁盘中。
RDB记录日志的内容
某一时刻的状态以文件的形式写到磁盘上,记录的是数据,而不是操作
给哪些内存数据做快照
全量快照
全量快照的问题
全量数据做快照,RDB文件大,磁盘写数据时间开销大
redis如何实现rdb的?
Redis会单独创建(fork)一个子进程,会先将数据写到一个临时文件中,待持久化过程都结束了,在用这个临时文件替换上次持久化好的文件,整个过程中,主进程不进行任何IO操作,保证了极高的性能,如果需要进行大规模数据恢复,且对于数据恢复的完成性不是非常敏感的,那么RDB的方式比AOF要高效,RDB的缺点是最后一次持久化的数据可能丢失
RDB 相关配置
- save
如果想禁用 RDB 配置,只需要在上面配置最后一行加上 save “” 即可 - stop-writes-on-bgsave-error
当 stop-writes-on-bgsave-error 设置为 yes 时,表示当备份进程出错时,主进程就会停止接收写入操作,从而保证了持久化数据的一致性
- rdbcompression
当 rdbcompression 设置为 yes 时,表示在备份的时候,需要将 RDB 文件进行压缩后再进行保存
这里建议将其设置为 no,因为 Redis 本身属于 CPU 密集型服务器,再开启压缩,会带来更多的 CPU 消耗,相比硬盘成本,CPU 性价比更高 - 生成的rdb文件名称为dump.rdb(配置文件的快照中进行配置)
rdb的触发机制
触发rdb持久化的方式有2种,分别是手动触发和自动触发。
手动触发
手动触发分别对应save和bgsave命令
-
save命令:阻塞当前Redis服务器,直到RDB过程完成为止,redis服务器在快照创建完毕之前将不在响应任何其他的命令,对于内存比较大的实例会造成长时间阻塞,线上环境不建议使用
-
bgsave命令:客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会调用fork来创建一个子进程,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件,而父进程则继续处理命令请求,Redis进程执行fork操作创建子进程,RDB持久化过程由子 进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短
bgsave流程图如下所示
具体流程如下:
- redis客户端执行bgsave命令或者自动触发bgsave命令;
- 主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回;
- 如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作;
- 子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件;
- 同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息(info Persitence下的rdb_*相关选项)。
自动触发
在以下4种情况时会自动触发
-
redis.conf中配置save m n,即在m秒内有n次修改时,自动触发bgsave生成rdb文件;
-
主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点; 执行debug
-
reload命令重新加载redis时也会触发bgsave操作; 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作;
如何恢复rdb文件
将rdb文件放到redis启动目录下就可以,redis在启动时会自动检查dump.rdb文件并恢复其中的数据
查看dump.rdb的文件位置
127.0.0.1:6379> config get dir #获取rdb文件位置
1) "dir"
2) "/usr/local/bin/yconfig"
127.0.0.1:6379>
做内存快照时,还能修改数据吗?
写入时复制,保证快照期间数据可修改
RDB快照就像平时的拍照一样,拍照的瞬间如果动了,照片就模糊了,就需要重拍,所以我们当然希望对方保持不动。对于内存快照而言,我们也不希望数据“动”。 如果快照执行期间不能修改,为了快照而暂停写操作,肯定是不能接受的。 以这个时候,Redis 就会借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作 。主线程修改数据,这块数据就被复制一份,生成副本,然后,bgsave子进程把副本写进RDB文件,在这个过程中,主线程依就可以修改原来的数据
两次快照间隔期间,宕机怎么办
最初的方案做全量快照后,后续快照做增量快照,带来新的问题:额外的空间开销
最终方案:混合使用AOF日志和快照的方法(redis4.0以后支持)
混合机制实现原理
内存快照以一 定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作 ,在第二次快照后,清空AOF日志
RDB-AOF混合模式
RDB-AOF 相关配置
当 aof-use-rdb-preamble 设置为 yes 时,表示开启 RDB-AOF 混合持久化模式
混合机制下的AOF重写
总结
在该模式下,AOF 重写产生的文件将同时包含 RDB 格式的内容和 AOF 格式的内容,该文件的前半段是 RDB 格式的全量数据,而后半段是 Redis 命令格式的增量数据。RDB 做全量持久化,AOF 做增量持久化由于 RDB 是间隔一段时间后才会进行持久化,在此期间内如果 Redis 服务出现问题,则会丢失这一段时间内的数据,因此需要 AOF 来配合使用在 Redis 重启时,会使用 BGSAVE 命令生成RDB 文件来重新构建内容,再使用 AOF 来重新执行近期的写指令,来实现数据的完整恢复
RDB的优缺点
优点
RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景;
Redis加载RDB文件恢复数据要远远快于AOF方式;
缺点
RDB方式实时性不够,无法做到秒级的持久化;
每次调用bgsave都需要fork子进程,fork子进程属于重量级操作,频繁执行成本较高;
RDB文件是二进制的,没有可读性,AOF文件在了解其结构的情况下可以手动修改或者补全;
版本兼容RDB文件问题;
针对RDB不适合实时持久化的问题,Redis提供了AOF持久化方式来解决