Redis持久化-RDB

        前面咱们说过,Redis 相对于 Memcache 等其余的缓存产品,有一个比较明显的优点就是 Redis 不只仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。这几种丰富的数据类型咱们花了两篇文章进行了详细的介绍,接下来咱们要介绍 Redis 的另一大优点——持久化。html

  因为 Redis 是一个内存数据库,所谓内存数据库,就是将数据库中的内容保存在内存中,这与传统的MySQL,Oracle等关系型数据库直接将内容保存到硬盘中相比,内存数据库的读写效率比传统数据库要快的多(内存的读写效率远远大于硬盘的读写效率)。可是保存在内存中也随之带来了一个缺点,一旦断电或者宕机,那么内存数据库中的数据将会所有丢失。redis

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

一、RDB 简介

  RDB是Redis用来进行持久化的一种方式,是把当前内存中的数据集快照写入磁盘,也就是 Snapshot 快照(数据库中全部键值对数据)。恢复时是将快照文件直接读到内存里。数据库

二、触发方式

  RDB 有两种触发方式,分别是自动触发和手动触发。数组

①、自动触发

  在 redis.conf 配置文件中的 SNAPSHOTTING 下,在这篇文章中咱们介绍过。缓存

  

  ①、save:这里是用来配置触发 Redis的 RDB 持久化条件,也就是何时将内存中的数据保存到硬盘。好比“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave(这个命令下面会介绍,手动触发RDB持久化的命令)服务器

  默认以下配置:数据结构

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

    固然若是你只是用Redis的缓存功能,不须要持久化,那么你能够注释掉全部的 save 行来停用保存功能。能够直接一个空字符串来实现停用:save ""app

  ②、stop-writes-on-bgsave-error :默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否中止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,不然没有人会注意到灾难(disaster)发生了。若是Redis重启了,那么又能够从新开始接收数据了异步

  ③、rdbcompression ;默认值是yes。对于存储到磁盘中的快照,能够设置是否进行压缩存储。若是是的话,redis会采用LZF算法进行压缩。若是你不想消耗CPU来进行压缩的话,能够设置为关闭此功能,可是存储在磁盘上的快照会比较大。

  ④、rdbchecksum :默认值是yes。在存储快照后,咱们还可让redis使用CRC64算法来进行数据校验,可是这样作会增长大约10%的性能消耗,若是但愿获取到最大的性能提高,能够关闭此功能。

  ⑤、dbfilename :设置快照的文件名,默认是 dump.rdb

  ⑥、dir:设置快照文件的存放路径,这个配置项必定是个目录,而不能是文件名。默认是和当前配置文件保存在同一目录。

  也就是说经过在配置文件中配置的 save 方式,当实际操做知足该配置形式时就会进行 RDB 持久化,将当前的内存快照保存在 dir 配置的目录中,文件名由配置的 dbfilename 决定。

②、手动触发

  手动触发Redis进行RDB持久化的命令有两种:

  一、save

  该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其余命令,直到RDB过程完成为止。

  显然该命令对于内存比较大的实例会形成长时间阻塞,这是致命的缺陷,为了解决此问题,Redis提供了第二种方式。

  二、bgsave

  执行该命令时,Redis会在后台异步进行快照操做,快照同时还能够响应客户端请求。具体操做是Redis进程执行fork操做建立子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,通常时间很短。

  基本上 Redis 内部全部的RDB操做都是采用 bgsave 命令。

  ps:执行执行 flushall 命令,也会产生dump.rdb文件,但里面是空的,无心义

三、恢复数据

  将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务便可,redis就会自动加载文件数据至内存了。Redis 服务器在载入 RDB 文件期间,会一直处于阻塞状态,直到载入工做完成为止。

  获取 redis 的安装目录可使用 config get dir 命令

  

四、中止 RDB 持久化

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

  也能够经过命令:

五、RDB 的优点和劣势

  ①、优点

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

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

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

  ②、劣势

  一、RDB方式数据没办法作到实时持久化/秒级持久化。由于bgsave每次运行都要执行fork操做建立子进程,属于重量级操做(内存中的数据被克隆了一份,大体2倍的膨胀性须要考虑),频繁执行成本太高(影响性能)

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

  三、在必定间隔时间作一次备份,因此若是redis意外down掉的话,就会丢失最后一次快照后的全部修改(数据有丢失)

六、RDB 自动保存的原理

  Redis有个服务器状态结构:

1
2
3
4
5
6
7
8
9
struct  redisService{
      //一、记录save条件的数组
      struct  saveparam *saveparams;
      //二、修改计数器
      long  long  dirty;
      //三、上一次执行保存的时间
      time_t  lastsave;
 
}

  ①、首先看记录保存save条件的数组 saveparam,里面每一个元素都是一个 saveparams 结构:

1
2
3
4
5
6
struct  saveparam{
      //秒数
      time_t  seconds;
      //修改数
      int  changes;
};

  前面咱们在 redis.conf 配置文件中进行了关于save 的配置:

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

  那么服务器状态中的saveparam 数组将会是以下的样子:

  

  ②、dirty 计数器和lastsave 属性

  dirty 计数器记录距离上一次成功执行 save 命令或者 bgsave 命令以后,Redis服务器进行了多少次修改(包括写入、删除、更新等操做)。

  lastsave 属性是一个时间戳,记录上一次成功执行 save 命令或者 bgsave 命令的时间。

  经过这两个命令,当服务器成功执行一次修改操做,那么dirty 计数器就会加 1,而lastsave 属性记录上一次执行save或bgsave的时间,Redis 服务器还有一个周期性操做函数 severCron ,默认每隔 100 毫秒就会执行一次,该函数会遍历并检查 saveparams 数组中的全部保存条件,只要有一个条件被知足,那么就会执行 bgsave 命令。

  执行完成以后,dirty 计数器更新为 0 ,lastsave 也更新为执行命令的完成时间。

相关文章
相关标签/搜索