redis持久化【RDB】

52 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

RDB快照是如何实现的?

由于AOF日志记录的是操作命令,不是实际的数据,所以使用AOF恢复数据时会造成redis恢复操作缓慢。

为了解决这样的问题,redis也提供了RDB快照的持久化技术。

RDB快照即保存某一瞬间的数据,记录的是实际的数据。

RDB做快照时会阻塞线程吗?

redis提供了两个命令来进行RDB快照。

  • save 在主线程中执行,会阻塞主线程
  • bgsave 会创建一个子进程来生成RDB文件,不会阻塞主进程。

redis也可以通过配置文件来自定义多久进行一次bgsave

save 900 1
save 300 10
save 60 10000

900 秒进行了1次修改

300 秒进行了10次修改

60 秒进行了10000次修改

另外,redis的快照是全量快照,记录的是当时内存中的所有数据。

RDB在执行快照的时候,数据能修改吗?

bgsave过程中,redis能够继续处理命令。用到的是写时复制技术。

  1. 在执行bgsave时,fork()创建子进程,此时子进程和父进程是共享同一片内存数据的,因为创建子进程的时候会复制父进程的页表,但是页表指向的物理内存还是同一个。
  2. 主进程进行写操作,被修改的部分会复制一份副本,子进程会对原来的数据写入到RDB,主进程可以继续修改数据。
  3. 但是bgsave 快照过程中,如果主线程修改了共享数据,发生了写时复制后,RDB 快照保存的是原本的内存数据,而主线程刚修改的数据,是被办法在这一时间写入 RDB 文件的,只能交由下一次的 bgsave 快照。

缺点:

  1. 如果系统恰好在 RDB 快照文件创建完毕后崩溃了,那么 Redis 将会丢失主线程在快照期间修改的数据。

  2. 在 Redis 执行 RDB 持久化期间,刚 fork 时,主进程和子进程共享同一物理内存,但是途中主进程处理了写操作,修改了共享内存,于是当前被修改的数据的物理内存就会被复制一份。

    那么极端情况下,如果所有的共享内存都被修改,则此时的内存占用是原先的 2 倍。

    所以,针对写操作多的场景,我们要留意下快照过程中内存的变化,防止内存被占满了。