Redis 持久化之 rdb

语言: CN / TW / HK

1、rdb 解决了什么问题?

rdb 是 redis 持久化其中的一种方案,通过快照的方式,可将内存的数据 dump 到磁盘上。

2、如何使用 rdb

2.1、save 与 bgsave

当客户端执行 save or bgsave 时, 服务端会将当前内存中的数据 dump 到文件上。

save 会拒绝客户端所有的命令,直到服务端执行完 save 后,才能响应客户端命令。

bgsave 命令不会阻塞客户端的读写命令。

2.2、自动触发 bgsave

2.2.1、开启自动触发 bgsave

在 redis 中默认是开启 rdb。例如下面的 redis 配置文件,格式如下: save <second> <changes>

save 900 1
save 300 10
save 60 10000

以上配置文件的意思为: 900s 内有一次修改、300s 内有 10次 修改、60s 内有 10000 次修改就会触发 bgsave 命令,将内存数据写入 dump.rdb 文件

2.2.1、关闭自动触发 bgsave

配置文件中保留 save "" 即可关闭该功能

2.3、配置文件中 rdb 相关配置

# rdb 文件存放目录
dir ./

# rdb 文件名称
dbfilename dump.rdb

# 备份时,是否压缩 rdb 文件
rdbcompression yes

# 重启redis时从rdb导入到内存中时检测rdb是否完成,文件有没有被损坏,版本兼容性等
rdbchecksum yes

#持久化失败后, 是否继续工作
stop-writes-on-bgsave-error yes 

#rdb文件是否删除同步锁
rdb-del-sync-files no

3、bgsave 原理

绝大部分情况下,我们不可能手动去执行 save or bgsave ,一般会依赖配置文件自动触发的 bgsave 进行数据快照。因此这里主要说 bgsave 的原理

3.1、基本概述

bgsave 会 fork 出一个子进程,由子进程执行数据快照。 其中 fork 动作会阻塞父进程,子进程执行数据快照时,不会阻塞父进程的读写操作。

3.2、子进程执行快照时,redis 如何做到不会阻塞父进程读写操作的?

fork 出来的 子进程与父进程共享同一份内存数据

当客户端要修改某一个 key 时,父进程会将当前要修改的 key 数据备份一份,然后在执行命令。子进程在执行快照时,读取的是 备份的数据。

以上简称为 写时复制技术 (实际上 java 中的 CopyOnWriteArrayList 实现思路也是类似)

图片来源:极客时间 《Redis核心技术与实战》 专栏

4、rdb 的弊端

假设在 T0 时刻执行了一次快照,在 T0 时刻后, redis 挂掉了,那么 T0 时刻后修改的数据就会丢失。

即:丢失最近一次快照后修改的数据。

5、灵魂拷问

5.1、bgsave 是不是真的不会阻塞父进程?

上文有说到,bgsave 会触发 fork 动作,fork 这个动作会阻塞父进程,且父进程的内存越大,阻塞就越久。子进程在创建后,就不会再阻塞父进程了。

分享到: