前面咱们说过,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是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 命令
有些状况下,咱们只想利用Redis的缓存功能,并不像使用 Redis 的持久化功能,那么这时候咱们最好停掉 RDB 持久化。能够经过上面讲的在配置文件 redis.conf 中,能够注释掉全部的 save 行来停用保存功能或者直接一个空字符串来实现停用:save ""
也能够经过命令:
①、优点
1.RDB是一个很是紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件很是适合用于进行备份和灾难恢复。
2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理全部保存工做,主进程不须要进行任何磁盘IO操做。
3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
②、劣势
一、RDB方式数据没办法作到实时持久化/秒级持久化。由于bgsave每次运行都要执行fork操做建立子进程,属于重量级操做(内存中的数据被克隆了一份,大体2倍的膨胀性须要考虑),频繁执行成本太高(影响性能)
二、RDB文件使用特定二进制格式保存,Redis版本演进过程当中有多个格式的RDB版本,存在老版本Redis服务没法兼容新版RDB格式的问题(版本不兼容)
三、在必定间隔时间作一次备份,因此若是redis意外down掉的话,就会丢失最后一次快照后的全部修改(数据有丢失)
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 也更新为执行命令的完成时间。