侧边栏壁纸
  • 累计撰写 247 篇文章
  • 累计创建 16 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Redis 数据持久化机制(下):RDB 快照篇

kaixindeken
2021-04-28 / 0 评论 / 1 点赞 / 110 阅读 / 1,559 字

RDB 是 Redis DataBase 的简写,所以 RDB 快照也就是 Redis 数据库快照,和 AOF 日志不同,它是系统某个时刻 Redis 数据库全量数据的快照,这意味着执行一次 RDB 快照需要遍历所有 Redis 键值对,然后持久化到磁盘,这两者都是耗时操作,因此,就不能在 Redis 主线程中进行 RDB 快照,否则会阻塞主线程,让 Redis 的高性能英名毁于一旦。

写时复制

为了保证高性能,Redis 采用了一种名为写时复制(Copy On Write,简称 COW)的多进程机制实现 RDB 快照。

具体说来,当需要进行 RDB 快照时,Redis 主进程会 fork 一个子进程出来,子进程会共享父进程 fork 时刻的内存数据,这就是要快照持久化的数据了,接下来,RDB 快照将在独立的子进程中进行,在此期间,Redis 主进程可以像之前一样正常处理客户端请求和响应,不会阻塞。

子进程在 RDB 快照期间,只会读取共享的 Redis 内存数据,然后将其持久化到磁盘,但是主(父)进程是在不断处理客户端请求的,这里面有读取指令,也有更新、删除指令,那这些更新操作会不会影响到 RDB 快照呢?

答案是不会。因为当有更新操作时,Redis 底层会通过操作系统的写时复制机制将这块数据复制一份分离出来,然后主进程直接修改原来的数据,子进程则会读取副本数据进行持久化,因此子进程对应的数据块是没有变化的,还是子进程 fork 时那一瞬间的数据,仿佛那一刻真的被按下快门,永久定格下来。

整个过程图示如下:

1.jpeg

当然,你也不需要担心这个写时复制会导致系统内存紧张,因为撑死了也不会超过原来 Redis 内存的 2 倍,何况 Redis 数据库中还有很多冷数据,但是我们在配置 Redis 内存上限时还是要考虑这些问题,留有余地,避免出现内存资源耗尽,Redis 服务不可用。

快照时机

一次持久化所有数据必然是个耗时操作,而且随着系统 Redis 数据的增长,这个时间也是不可控的,不可能像 AOF 日志那样做到每秒一次快照,那么 Redis 底层是如何规划 RDB 快照的时机的呢?

我们可以通过 Redis 配置文件 redis.conf 的 save 配置项进行配置,默认配置如下:

save 900 1
save 300 10
save 60 10000

对应的含义是:

  • 如果 900 秒(15 分钟)内至少有 1 个键修改,则执行一次 RDB 快照;
  • 如果 300 秒(5 分钟)内至少有 10 个键修改,则执行一次 RDB 快照;
  • 如果 60 秒(1 分钟)内至少有 10000 个键修改,则执行一次 RDB 快照。

这是服务端自动执行 RDB 快照的机制,除此之外,你还可以通过 Redis 客户端发送如下指令主动进行 RDB 快照持久化:

  • save:在 Redis 主线程同步进行 RDB 快照,会阻塞主线程;
  • bgsave:这也是 Redis 服务端默认的 RDB 快照机制,会 fork 一个子进程进行 RDB 快照,不会阻塞主线程。

可以看到,最快的情况下,RDB 快照也是 1 分钟执行一次,如果数据更新频繁,RDB 快照的滞后还是很明显的,所以,目前 Redis 采用的是 RDB + AOF 混合持久化机制,既充分利用了 RDB 快照恢复快,又充分利用了 AOF 日志数据丢失率低(至多 1 秒)。

1

评论区