15. Redis 持久化 RDB 操作

zhanglei 2022年07月28日 343次浏览

15. Redis 持久化 RDB 操作

为什么要持久化

由于 Redis 是一个内存数据库,所谓内存数据库,就是将数据的内容保存在内存中。这与传统的 MySQL,Oracle 等关系型数据库直接将内容保存到硬盘中相比,内存数据库的读写效率比传统数据库要快得多(内存的读写效率远远大于硬盘的读写效率)。但是数据保存在内存也有缺点:一旦断电或者宕机,内存数据库中的数据将会全部丢失。

为了解决这个缺点,Redis提供了将内存数据持久化到硬盘,以及用持久化文件来恢复数据库数据的功能。Redis 支持两种形式的持久化,一种是RDB快照(snapshotting),另外一种是AOF(append-only-file)

RDB (Redis database)

RDB 是 Redis 用来进行持久化的一种方式,是把当前内存中的数据集快照写入磁盘,也就是 Snapshot 快照(所谓“快照”就是将内存数据以二进制文件的形式保存起来。)。恢复时是将快照文件直接读到内存里。

在默认情况下,Redis 将数据库快照保存在名字为dump.rdb 的二进制文件中。

image-20220728195310212

RDB 持久化的触发策略

RDB 持久化提供了两种触发策略:一种是手动触发,另一种是自动触发

手动触发

手动触发是通过SAVAE命令或者BGSAVE命令将内存数据保存到磁盘文件中。如下所示:

127.0.0.1:6379> set name zhanglei
OK
127.0.0.1:6379> save      # 第一种手动触发方式
OK
127.0.0.1:6379> set name lutingting
OK
127.0.0.1:6379> bgsave    # 第二种手动触发方式
Background saving started
127.0.0.1:6379> 

save

img

bgsave

img

基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。

自动触发

在 redis.conf 中:

image-20220728183921320

save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存
save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存
save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存

你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动执行bgsave,保存一次数据集,生成 dump.rdb 文件。

停止 RDB 持久化

有些情况下,我们只想利用Redis的缓存功能,并不像使用 Redis 的持久化功能,那么这时候我们最好停掉 RDB 持久化。可以通过上面讲的在配置文件 redis.conf 中,可以注释掉所有的 save 行来停用保存功能或者直接一个空字符串来实现停用:save ""

也可以通过命令:

redis-cli config set save " "

RDB 的优势和劣势

优势

1.RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。

2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。

3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

劣势

1、RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,如果不采用压缩算法,频繁执行成本过高(影响性能)

2、RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题(版本不兼容)

3、在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失)

RDB 自动保存的原理

RDB 实际上是 Redis 内部的一个定时器事件,它每隔一段固定时间就去检查当前数据发生改变的次数和改变的时间频率,看它们是否满足配置文件中规定的持久化触发条件。当满足条件时,Redis 就会通过操作系统调用 fork() 来创建一个子进程,该子进程与父进程享有相同的地址空间。

Redis 通过子进程遍历整个内存空间来获取存储的数据,从而完成数据持久化操作。注意,此时的主进程则仍然可以对外提供服务,父子进程之间通过操作系统的 COW 机制实现了数据段分离,从而保证了父子进程之间互不影响。