Redis持久化

113 阅读7分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情

1、持久化流程

Redis是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化是很快的,也容易发生丢失。这时Redis为我们提供了持久化的机制,分别是RDB(Redis DataBase)AOF(Append Only File)

redis的数据可以保存在磁盘上,那么这个流程是什么样的呢? 主要有下面五个过程:

  1. 客户端向服务端发送写操作(数据在客户端的内存中)。
  2. 数据库服务端接收到写请求的数据(数据在服务端的内存中)。
  3. 服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
  4. 操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中。
  5. 磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。

以上五个步骤是我们理想下的一个正常的保存流程,但是在大多数情况下,我们的机器等等都会有各种各样的故障,这里划分了两种情况:

  1. Redis数据库发生故障,只要在上面的第三步执行完毕,那么就可以持久化保存,剩下的两步由操作系统替我们完成。
  2. 操作系统发生故障,必须上面5步都完成才可以。

所以我们现在考虑的是redis如何来实现上面5个保存磁盘的步骤。它提供了两种策略机制,也就是RDB和AOF

2、RDB

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb

2.1、优点

  • RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。
  • RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心,或者亚马逊 S3 中。
  • RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
  • RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
  • 适合大规模的数据恢复
  • 对数据完整性和一致性要求不高

Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量,环境变量,程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

2.2、缺点

  • 如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。
  • 每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork() ,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。
  • 在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改
  • Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。

Rdb 保存的是 dump.rdb 文件

2.3、快照规则

save:这里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。

比如"save m n"。表示m秒内数据集存在n次修改时,自动触发bgsave。

配置位置及SNAPSHOTTING解析(在第三章的相关配置中有介绍)

默认如下配置:

# 900秒(15分钟)内至少1个key值改变,才会进行保存(则进行数据库保存--持久化)
save 900 1
​
# 300秒(5分钟)内至少10个key值改变,才会进行保存(则进行数据库保存--持久化)
save 300 10
​
# 60秒(1分钟)内至少10000个key值改变,才会进行保存(则进行数据库保存--持久化)
save 60 10000

我们可以修改触发条件机制:

save 120 10 # 120秒内修改10次则触发RDB

RDB 是整合内存的压缩过的Snapshot(快照),RDB 的数据结构,可以配置复合的快照触发条件。

默认:

  • 1分钟内改了1万次
  • 5分钟内改了10次
  • 15分钟内改了1次

如果想禁用RDB持久化的策略,只要注释掉所有的 save,或者给save传入一个空字符串参数也可以。

若要修改完毕需要立马生效,可以手动使用 save 命令!立马生效 !

其余配置文件解析:

Stop-writes-on-bgsave-error:如果配置为no,表示你不在乎数据不一致或者有其他的手段发现和控 制,默认为yes。

rbdcompression:对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用 LZF算法进行压缩,如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能。

rdbchecksum:在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约 10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。默认为yes。

2.4、触发RDB快照

1、配置文件中默认的快照配置,建议多用一台机子作为备份,复制一份 dump.rdb

2、命令save或者是bgsave

  • save 时只管保存,其他不管,全部阻塞,执行该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止

  • bgsave,Redis 会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过lastsave 命令获取最后一次成功执行快照的时间。

3、执行flushall命令,也会产生 dump.rdb 文件,但里面是空的,无意义 !

4、退出的时候也会产生 dump.rdb 文件。

具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。

2.5、修复

1、将备份文件(dump.rdb)移动到redis安装目录并启动服务即可

2、CONFIG GET dir 获取目录

127.0.0.1:6379> config get dir
dir
/usr/local/bin

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