写在前面
Redis是一个内存数据库,他将自己的数据存储在内存中,如果没有办法将内存的数据存储到磁盘,那么一旦发生宕机,这些数据将会消失。这篇文章我们就讲讲Redis的持久化RDB。
1. 简介
RDB 全称 Redis DataBase,可以将Redis在内存中的数据库状态生成一个RDB文件保存在磁盘中。RDB既可以手动执行,也可以根据服务器配置选项定期执行。
同样的RDB文件也可以转化成Redis数据库状态,所以即使Redis宕机了,只要及时保存RDB在磁盘中,就能使用磁盘的RDB文件恢复Redis的数据库状态。
2. RDB的创建与加载
2.1 创建
有两个Redis命令可以创建RDB文件,SAVE和BGSAVE
。这两个命令的区别在于:SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。
而BGSAVE是则会fork出一个子进程,然后由这个子进程负责创建RDB文件,主进程继续处理命令请求。
2.2 载入
RDB文件的载入工作是在服务器启动时,自动执行的,所以Redis并没有专门用于载入RDB文件的命令,只要Redis服务器在启动时检测到RDB文件存在,就会自动载入RDB文件。
这里注意一点,我们知道除了RDB持久化,Redis还有AOF持久化,而AOF的更新频率通常来说是比RDB高的,也就意味着AOF中的数据会更新。
所以如果Redis服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态。只有在AOF关闭的时候,才会使用RDB。
而服务器在RDB载入期间也是处于阻塞状态,直到载入工作完成为止。
3. RDB文件结构
- RDB文件的最开头是REDIS部分,这个部分的长度为5字节,保存着REDIS五个字符,通过这五个字符,程序可以在载入文件时,快速检查所载入的文件是否为RDB文件。
- db_version 长度为4字节,是一个字符串表示的整数,
这个数值记录了RDB的版本
,比如“0003” 就代表RDB文件为第3版。 - databases 中包含着零个或任意多个数据库,
以及各个数据库中键值对数据。
- EOF常量的长度为1字节,这个常量标志着RDB文件的读取结束。当程序读到这里的时候,就意味着已经结束了,所有的键值都已经加载完了。
- check_sum 是一个8字节长的无符号整数,保存着一个校验和,这个校验和是根据前四个部分进行计算得出来的。
服务器加载完数据后,会通过将载入的数据做运算和check_sum做比较,来检验RDB文件是否有损坏。
3.1 databases
一个RDB文件中的databases部分可以保存任意多个非空的数据库。
而每个databases在RDB中都可以保存为以下这种形式
- SELECTDB 长度为1字节,类似于上面5字节的REDIS的作用,当读到这个值的时候,意味着下一位是读一个数据库号码了
- db_number保存着一个数据库号码,比如database 0 这里存储的就是 0
- key_value_pairs:保存了所有的键值对数据嘛,如果键值队带有过期时间,那么这个过期时间也会跟着一起保存在一起。
3.2 key value pairs
key_value_pairs保存了所有的键值对数据嘛,如果键值队带有过期时间,那么这个过期时间也会跟着一起保存在一起
。不带过期时间的key就比如下面这个:
TYPE 记录了value的类型,长度为1字节,代表redis的所有类型,string、list、set、zset等等…
而带有过期时间的key的结构如下:
- 新增的 REPIRETIME_MS 长度1字节,这是告诉程序,
接下来要读入一个以毫秒为单位的过期时间
。 - 而ms字段是一个8字节的长的带符号的整数,
记录一个以毫秒为单位的UNIX时间戳
,这个时间戳就是这个键值对的过期时间。