15. Redis 持久化 RDB 操作
为什么要持久化
由于 Redis 是一个内存数据库
,所谓内存数据库,就是将数据的内容保存在内存中。
这与传统的 MySQL,Oracle 等关系型数据库直接将内容保存到硬盘中
相比,内存数据库的读写效率比传统数据库要快得多(内存的读写效率远远大于
硬盘的读写效率)。但是数据保存在内存也有缺点:一旦断电或者宕机,内存数据库中的数据将会全部丢失。
为了解决这个缺点,Redis提供了将内存数据持久化到硬盘,以及用持久化文件来恢复数据库数据的功能。Redis 支持两种形式的持久化,一种是RDB快照(snapshotting)
,另外一种是AOF(append-only-file)
。
RDB (Redis database)
RDB 是 Redis 用来进行持久化的一种方式,是把当前内存中的数据集
快照写入磁盘,也就是 Snapshot 快照(所谓“快照”就是将内存数据以二进制文件的形式保存起来。)。恢复时是将快照文件直接读到内存里。
在默认情况下,Redis 将数据库快照保存在名字为dump.rdb
的二进制文件中。
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
bgsave
基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。
自动触发
在 redis.conf 中:
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 机制实现了数据段分离,从而保证了父子进程之间互不影响。