美文网首页Redis
四、Redis数据快速恢复之RDB(Redis DataBase

四、Redis数据快速恢复之RDB(Redis DataBase

作者: 龚志丹 | 来源:发表于2020-11-23 17:25 被阅读0次

    什么是RDB?

    内存快照(将内存中的数据在某一时刻的状态记录至磁盘中)。现实可以理解为拍照。

    想象下如果100个人(数据)在拍照,那首先想到的问题这100个人给谁拍照?拍照的同时如果有人"动"了怎么办?基于这些场景繁衍以下问题:

    RDB对哪些数据做快照?(执行效率问题)(给谁拍照?)

    全量快照,一次性记录所有数据,保证数据的完整性

    RDB执行的过程中会不会阻塞线程?

    Redis 两个命令生成 RDB 文件, save 和 bgsave。
    save:在主线程中执行,导致阻塞;
    bgsave:创建一个子进程,用于写入 RDB 文件,避免主线程阻塞。(Redis默认配置项使用bgsave)。

    RDB在做快照时Redis还能修改吗?(如果有人动了怎么办?当然我们是不希望他们动)

    采用bgsave因为Redis会fock一个子进程处理,所以读肯定没问题,修改是怎么处理的呢?
    Redis借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作。具体流程:

    主线程 fork 出 bgsave 子进程后,bgsave 子进程实际是复制了主线程的页表。这些页表中,就保存了在执行 bgsave 命令时,主线程的所有数据块在内存中的物理地址。这样一来,bgsave 子进程生成 RDB 时,就可以根据页表读取这些数据,再写入磁盘中。如果此时,主线程接收到了新写或修改操作,那么,主线程会使用写时复制机制。具体来说,写时复制就是指,主线程在有写操作时,才会把这个新写或修改后的数据写入到一个新的物理地址中,并修改自己的页表映射。

    如图:


    写时复制

    bgsave 子进程复制主线程的页表以后,假如主线程需要修改虚页 7 里的数据,那么,主线程就需要新分配一个物理页(假设是物理页 53),然后把修改后的虚页 7 里的数据写到物理页 53 上,而虚页 7 里原来的数据仍然保存在物理页 33 上。这个时候,虚页 7 到物理页 33 的映射关系,仍然保留在 bgsave 子进程中。所以,bgsave 子进程可以无误地把虚页 7 的原始数据写入 RDB 文件。

    如果每秒做一次快照会有什么问题?

    一、频繁将全量数据写入磁盘,会给磁盘带来很大压力,多个快照竞争有限的磁盘带宽,前一个快照还没有做完,后一个又开始做了,容易造成恶性循环。
    二、bgsave 子进程需要通过 fork 操作从主线程创建出来。虽然,子进程在创建后不会再阻塞主线程,但是,fork 这个创建过程本身会阻塞主线程,而且主线程的内存越大,阻塞时间越长。

    对比AOF

    快照的恢复速度快,频率无法把控,频率太低,宕机,丢失数据比较多。频率太高,产生额外开销。

    怎么使用RDB既能恢复快、又能降低开销?

    混合使用 AOF 日志和内存快照,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。

    相关文章

      网友评论

        本文标题:四、Redis数据快速恢复之RDB(Redis DataBase

        本文链接:https://www.haomeiwen.com/subject/dyemiktx.html