文章目录
持久化的概念
Redis
支持AOF
和RDB
两种持久化机制,持久化功能能有效的避免因进程退出而导致的数据丢失 的问题,当下次重启的时候利用之前持久化的文件即可实现数据恢复 .
所以此时我们要明确一个常见的误区:Redis不仅仅会将数据保存在内存中,还会将数据保存在磁盘中 ,实现持久化存储
RDB
RDB
持久化是指把当前进程数据生成快照 保存到硬盘 中的过程,触发RDB
持久化过程分为手动触发 和自动触发
- 快照:快照可以理解为把当前内存 中存储的数据拍一个照片,生成一个文件,即是一种瞬时的保存
RDB
:相当于定期备份 ,把内存中所有的数据写入硬盘中,生成一个快照
手动触发
手动触发的意思就是由 程序员通过Redis
客户端来执行持久化的命令
save
命令:阻塞当前的Redis
服务器,直到RDB
过程完成为止,对于内存比较大的实例会造成阻塞时间过长 ,基本不采用 .(Redis
是单线程 ,阻塞了Redis
接受其他客户端的指令)bgsave
命令::Redis
进程执行fork
操作创建子进程 ,RDB
持久化过程是由子进程 负责的,完成之后自动结束 .阻塞只发生在fork
阶段,一般来说时间比较短 (Redis
在主线程中只进行了fork
创建子进程的操作)
自动触发
Redis
运行自动触发RDB
持久化机制,这个触发机制在实战中才是比较有价值的.
- 使用
save
配置.如save m n
表示m
秒内数据集发生了n
次修改,自动进行RDB
持久化.(可在配置文件中进行修改) - 从节点进行全量复制 操作时,主节点自动进行
RDB
持久化,所有将RDB
文件发送给从节点 - 执行
shutdown
命令关闭Redis
时,执行RDB
持久化.(使用showdown
等命令关闭Redis
属于正常关闭 ,如果发生异常关闭 ,可能会导致数据的丢失)
bgsave
命令的运行流程
- 执行
bgsave
命令,Redis
父进程判断当前进程是否存在其他正在执行的子进程,如RDB/AOF
子进程,如果存在bgsave
命令直接返回 - 父进程执行
fork
创建子进程,fork
过程中父进程会阻塞,通过info stats
命令查看last_fork_usec
选项,可以获取最近一次fork
操作的耗时,单位为毫秒 - 父进程
fork
完成之后,bgsave
命令返回Background saving started
信息不再阻塞父进程,可以相应其他的命令 - 子进程创建
RDB
文件.根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换 .执行lastsave
命令可以获得最后一次生成RDB
的时间,对应info
统计的rdb_last_save_time
选项 - 进程发送信号给父进程表示完成 ,父进程更新统计信息
RDB
文件的处理
- 静态保存 :
RDB
文件保存在dir
配置指定的目录(默认为/var/lib/redis
下),文件名通过dbfilename
配置(默认dump.rdb
)指定. - 动态保存 :可以通过执行
config set dir {newDir}
和config set dbfilename {dbFilename}
运行期间动态执行,当下次运行时RDB
文件会被保存在新的目录中 - 压缩 :
Redis
默认采用LZF
算法对生成的RDB
文件进行压缩处理 ,压缩后的文件远远小于内存大小,可以通过参数config set rdbcompression{yes|no}
来进行动态修改 - 校验 :如果
Redis
启动时加载到损坏的RDB
文件,会拒绝启动 .这时可以使用Redis
提供的redis-check-dump
工具检测RDB
文件并获取对应的错误报告
RDB
的优缺点
优点
RDB
是一个紧凑压缩的二进制文件 ,代表Redis
在某个时间点上的数据快照 .非常适用于备份 ,全量复制 等场景.即适合定期备份的场景- 由于
RDB
是以二进制来组织数据 ,而AOF
是以文本的形式来组织数据,所以Redis
加载RDB
恢复数据远远快于AOF
的方式
缺点
RDB
方式数据没办法做到实时持久化/秒级持久化 .因为bgsave
每次运行都要执行fork
创建子进程,属于重量级 操作,频繁执行成本过高,所以在两次快照数据存储之间的数据可能存在数据丢失的可能RDB
文件使用特定的二进制格式保存,Redis
版本演进过程中有多个RDB
版本,兼容性可能有风险.
RDB
效果展示
我们先来大致总结一下RDB
文件的触发条件:
- 手动触发:
save
和bgsave
,其中最常使用的是bgsave
- 自动触发:
- 在配置文件中进行触发条件的配置
save m n
- 正常关闭
Redis
时,会触发RDB
,但是异常关闭Redis
时,可能会导致没有触发RDB
持久化导致数据丢失
- 在配置文件中进行触发条件的配置
接下来我们使用bgsave
来进行RDB
效果展示
先展示正常存储的情况:
- 当
Redis
中没有存放任何数据时,我们来观察一下rdb
文件中的数据情况
- 接下来向
Redis'
中存放几个key
- 再执行
bgsave
,手动触发RDB
持久化
- 再来观察
RDB
文件中的数据改变
我们发现,数据中出现了key1
,key2
,key3
等的身影,说明数据已经被持久化到磁盘文件中了
如果我们不进行bgsave
手动触发呢?
我们来看看具体的情况(在执行之前已经清空了所有的数据,恢复到原始状态):
-
先向
Redis
中添加几个数据:
-
不执行
bgsave
直接退出,此时打开rdb
文件观察:
没有发现明显的
key
数据的身影. -
再打开
Redis
观察数据:
这里为什么
RDB
文件中不存在数据,但是在Redis
服务端中还能查询到对应的数据呢?这是因为,我们的数据虽然没有被持久化到对应的磁盘文件
dump.rdb
文件中,但是依旧保存在内存 中,所以如果我们在没有断开Redis
服务端的情况下,还是可以再一次查询到对应的数据的.但是,如果我们此时模拟异常关闭的情况 ,即kill -9 Redis-server的进程ID
,再启动对应的Redis
,我们再来观察数据是否还存在: -
kill -9 Redis-server的进程ID
-
再启动
Redis
:redis-server /etc/redis/redis.conf
-
查询数据情况:
此时我们发现,数据不存在,这样便验证了我们的猜想:刚才的数据是存储在内存中的,而不是磁盘中 ,同时,我们也得出结论:异常关闭 会导致数据丢失
接下来我们来验证一下:正常关闭是否会触发RDB
持久化行为
redis-cli shutdown
属于正常关闭Redis
的行为
-
向
Redis
中存放多个数据
-
再执行正常的关闭
Redis
的行为:redis-cli shutdown
,再重启Redis
-
查看其中的数据:
-
查看
RDB
文件:
发现正常关闭
Redis
的行为自动触发 了RDB
持久化行为.