前言
从上篇 RedisTemplate 可没你想的那么简单 完结后,整个 Redis 的客户端相关的就弄完了,主要是
Jedis
、Lettuce
、RedisTemplate
三篇。有不熟悉的好哥哥可以去我的文章那里翻翻,说不定就会有不一样的收获。今天的这篇的话是关于 Redis 持久化相关的第一篇,后续应该会有几篇关于持久化的,好哥哥们好好看,主要是要动手操作起来。当然如果只是为了应付面试的话可以大概的看看,但是还是建议这一块相关的东西系统的看看。看完记得点赞加关注哟。
概述
Redis 系列第一篇 初识 Redis 中就有提到说 Redis 是一个基于内存的非关系性数据库。那所谓内存数据库,就是将数据库中的内容保存在内存中,这与传统的MySQL
,Oracle
等关系型数据库直接将内容保存到硬盘中相比,内存数据库的读写效率比传统数据库要快的多(内存的读写效率远远大于硬盘的读写效率)。但是保存在内存中也随之带来了一个缺点,一旦断电或者宕机,那么内存数据库中的数据将会全部丢失。
为了解决这个缺点,Redis 提供了将内存数据持久化到硬盘,以及用持久化文件来恢复数据库数据的功能。Redis 支持两种形式的持久化,一种是RDB
快照(snapshotting),另外一种是AOF
(append-only-file)。
RDB
RDB
持久化是把当前进程数据生成快照保存到硬盘的过程。能够在指定时间间隔内对数据进行快照存储,默认情况下,Redis 将数据快照保存在dump.rdb
这个二进制的文件中。触发RDB
持久化过程分为手动触发和自动触发。
触发机制
上面有提到触发分为手动触发和自动触发。手动触发又分成了两种方式,第一种使用save
,第二种使用bgsave
。
手动触发-save
save
会阻塞当前 Redis 服务器,直到RDB
过程完成为止,对于内存比较大的实例会造成长时间阻塞,线上环境不建议使用。命令如下:
127.0.0.1:6379> save OK 复制代码
手动触发-bgsave
上面提到了就是save
是一个阻塞操作。假设在生产环境中使用这个命令,如果数据量够大,那么会使 Redis 服务器阻塞的时间非常长,导致 Redis 服务的不可用。bgsave
就是用来解决这个问题的,bgsave
执行时,Redis 进程会执行fork
操作创建子进程,RDB 持久化过程由子进程负责,完成后自动结束。阻塞只发生在 fork 阶段,一般时间很短。
127.0.0.1:6379> bgsave Background saving started 复制代码
整个过程如下:
save-bgsave 对比
命令 | save | bgsave |
---|---|---|
类型 | 同步 | 异步 |
是否阻塞 | 是 | 只有在 fork 是阻塞的 |
优点 | 没有额外的内存消耗 | 不会阻塞服务器 |
缺点 | 阻塞服务器 | 需要 fork 创建子进程,额外消耗内存 |
自动触发
除了执行命令手动触发之外,Redis 内部还存在自动触发RDB
的持久化机制。触发的逻辑是 Redis 在 N 秒内有 M 个键被改动,好哥哥们可以通过修改配置文件来实现对RDB
的自动触发。默认配置如下:
## 表示 900 秒内如果至少有 1 个 key 的值变化,则触发 save 900 1 ## 表示300 秒内如果至少有 10 个 key 的值变化,则触发 save 300 10 ## 表示60 秒内如果至少有 10000 个 key 的值变化,则触发 save 60 10000 复制代码
其他 RDB 相关配置:
## bgsave写入错误是否停止写入 stop-writes-on-bgsave-error yes ## 是否对rdb文件使用压缩格式 rdbcompression yes ## 是否对rdb文件校验 rdbchecksum yes ## rdb持久化名称 dbfilename dump.rdb ## rdb持久化存放目录 dir ./ 复制代码
自动触发原理
Redis 服务器维护了一个状态结构,其中包括save条件的数组(saveparams)
、计数器(dirty)
、上次保存时间(lastsave)
。前面我们在 redis.conf
配置文件中进行了关于save
的配置,解析成条件的数组后就是下面的样子:
当服务器成功执行一次修改操作,那么计数器(dirty)
就会加 1。而lastsave
属性记录上一次执行save
或bgsave
的时间,Redis 服务器还有一个周期性操作函数 severCron
,默认每隔 100 毫秒就会执行一次,该函数会遍历并检查 saveparams
数组中的所有保存条件,只要有一个条件被满足,那么就会执行 bgsave
命令。 执行完成之后,计数器(dirty)
更新为 0 ,lastsave
也更新为执行命令的完成时间。