RDB内存快照原理详解

是什么

  • 内存快照, 就是指内存中的数据在某一个时刻的状态记录,即某一时刻的状态以文件的形式写到磁盘上。
  • 快照是一次的全量备份、是内存数据的二进制序列化。
  • 在做数据恢复时,我们可以直接把 RDB 文件读入内存,很快地完成恢复

文件结构

基本结构

在这里插入图片描述

  • REDIS:常量,5个字节,标识是否是RDB文件
  • db_version:变量,4个字节,记录了RDB文件版本号
  • databases:数据,包含着0到n个数据库,以及各个数据库中的键值对
  • EOF:常量,1字节,标志RDB文件正文内容的结束
  • check_sum:变量,8字节,保存校验和,对以上四部分进行计算得出来的值,用于检查RDB文件是否有出错或者损坏的情况
databases结构

databases里加入有两个数据库,结构如下
在这里插入图片描述
database详细结构如下
在这里插入图片描述

  • SELECTDB:常量,1字节,代表下一个要读入的是个数据库号码
  • db_number:变量,大小不定,数据库号码
  • key_value_pairs:保存了数据库的所有键值对数据

两个问题

  • 对哪些数据做快照关系到快照的执行效率问题:全量快照
  • 快照时Redis 是否被阻塞,能否同时正常处理增删改:不阻塞,能常常增删改

两个命令

通过两个命令来生成 RDB 文件,分别是 save 和 bgsave。

  • save : 在主线程中执行,会导致阻塞,直到RDB文件创建完毕
  • bgsave : fork一个子进程专门用于写入 RDB 文件,避免了主线程的阻塞(默认配置)

快照数据修改(COW机制)

Redis 就会借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作。

bgsave中子进程是由主线程 fork 生成的,可以共享父进程内存里面的代码段和数据段数据,进程分离的一瞬间,内存的增长几乎没有明显变化, bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。

如果主线程要修改一块数据(例如图中的键值对 C), 那么,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

在这里插入图片描述
随着父线程修改操作的持续进行,越来越多的共享页面被分离出来,内存就会持续增长,但是不会超过内存的两倍大小。

子进程因为能看到的数据在进程产生的一瞬间就再也不会改变了,所以把RDB这种持久化叫做快照。

快照的频率

如果频繁地执行全量 快照,也会带来两方面的开销。

  • 频繁将全量数据写入磁盘,会给磁盘带来很大压力,多个快照竞争有限的磁盘带宽,前后交叉,容易造成恶性循环。
  • bgsave 子进程通过 fork 操作从主线程创建出来,fork 这个创建过程本身会阻塞主线程,之后不会。
    • fork主线程的内存越大,阻塞时间越长
    • 如果频繁 fork 出 bgsave 子进程,这就会频繁阻塞主线程了。
增量快照

做了一次全量快照后,后续的快照只对修改的数据进行快照记录,这样可以避免每次全量快照的开销。

和AOF 相比,快照的恢复速度快,但快照的频率不好把握

  • 如果频率太低,两次快照间一旦宕机,就可能有比较多的数据丢失。
  • 如果频率太高, 又会产生额外开销

在第一次做完全量快照后,T1 和 T2 时刻如果再做快照,我们只需要将被修改的数据写入 快照文件就行。但是,这么做的前提是,我们需要记住哪些数据被修改了。

在这里插入图片描述

混合日志和快照

Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。
内存快照以一 定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。
在这里插入图片描述

RDB文件的载入工作是在服务器启动时自动执行的,载入过程中一直处于阻塞状态,直至载入完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值