一、什么是RDB机制

 

    RDB 是 Redis DataBase 的缩写,即内存块照。因为Redis的数据时存在内存中的,当服务器宕机时,Redis中存储的数据就会丢失。这个时候就需要内存快照来恢复Redis中的数据了。快照就是在某一时刻,将Redis中的所有数据,以文件的形式存储起来。这就类似于照片,当你给朋友拍照时,一张照片就能把朋友一瞬间的形象完全记下来。

二、RDB机制是如何实现的

    1、全量快照

    Redis 的数据都在内存中,为了提供所有数据的可靠性保证,它执行的是全量快照,也就是说,把内存中的所有数据都记录到磁盘中,这就类似于给 100 个人拍合影,把每一个人都拍进照片里。这样做的好处是,一次性记录了所有数据,一个都不少。

    这样就会产生一个问题,当Redis中的数据越大时,快照文件写入磁盘的时间也就越长。那么Redis在写入磁盘的时候会阻塞主线程吗?这就关系到是否会影响Redis的性能了。

    Redis提供了两个命令来生产全量的RDB文件,一个是 save ,另一个是 bgsave。

    save:在主线程中执行,会导致阻塞;

    bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。

不用想也知道,我们应该使用哪种方式来生成RDB文件了。

    我们知道了,RDB文件生成的两种命令,那么接下来说下他的具体实现逻辑:

     如上图所示,快照开始时,主线程会fork出一个用于快照操作的子线程,并且复制一份数据对应的映射页表给子线程。子线程可以通过这个页表访问主线程的原始数据,然后将数据生成快照文件,存储到磁盘中。我们知道存储磁盘的时间是比较长的,当这个时候有请求进行想写数据怎么办呢?

    这个时候就要用到 写时复制,即当请求需要对键值C进行操作时,主线程会把新数据或修改后的数据写到一个新的物理内存地址上(键值对C'),并修改主线程自己的页表映射。所以,子进程读到的类似于原始数据的一个副本,而主线程也可以正常进行修改。

    这既保证了快照的完整性,也允许主线程同时对数据进行修改,避免了对正常业务的影响。

2、增量快照

   如果一直使用全量同步,一方面时间的推移,磁盘存储的快照文件会越来越多。另一方面如果频繁的进行全量同步,则需要主线线程频繁的fork出bgsvae线程,这样对Redis的性能是会产生影响的,并且也需要持续的对磁盘进行写操作。

   这个时候,我们可以采用另一只同步方式:增量快照。所谓增量快照,就是指,做了一次全量快照后,后续的快照只对修改的数据进行快照记录,这样可以避免每次全量快照的开销。在第一次做完全量快照后,T1 和 T2 时刻如果再做快照,我们只需要将被修改的数据写入快照文件就行。但是,这么做的前提是,我们需要记住哪些数据被修改了。你可不要小瞧这个“记住”功能,它需要我们使用额外的元数据信息去记录哪些数据被修改了,这会带来额外的空间开销问题。如下图所示:

 如果我们对每一个键值对的修改,都做个记录,那么,如果有 1 万个被修改的键值对,我们就需要有 1 万条额外的记录。而且,有的时候,键值对非常小,比如只有 32 字节,而记录它被修改的元数据信息,可能就需要 8 字节,这样的画,为了“记住”修改,引入的额外空间开销比较大。这对于内存资源宝贵的 Redis 来说,有些得不偿失。

所以说,全量快照和增量快照都有各自的优点和缺点,至于实际应用时,则要根据具体情况进行权衡。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐