RDB持久化:
- rdb持久化可以把Redis在内存中的数据库状态保存到磁盘里面,避免数据意外丢失。
- redis在需要时可以将数据库状态保存为RDB文件,也可以将RDB文件还原为数据库状态。
1. RDB文件的创建与载入
-
SAVE 和BGSAVE 都可以生成RDB文件
-
save:会阻塞Redis的服务器进程,知道RDB文件创建完毕,阻塞期间,服务器不能处理任何命令请求,客户端发送的所有命令请求都会被拒绝。
-
bgsave:派生出子进程,由子进程负责创建RDB文件,父进程继续处理命令请求。bgsave命令执行期间:
-
客户端发送的save命令会被拒绝。(save和bgsave不能同时进行,为了避免父子进程同时执行两个rdbSave调用,防止产生竞争条件)
-
客户端发送的bgsave也会被拒绝。同时执行两个bgsave命令也会产生竞争条件
-
客户端发送的bgrewriteaop不能和bgsave同时执行。
- 如果bgsave正在执行,那么bgrewriteaop会被延迟到bgsave命令执行完毕后执行。
- 如果bgrewriteaop正在执行,那么bgsave会被服务器拒绝。
因为这两个命令都是由子进程执行,在操作上没有冲突的地方,但是因为两个子进程如果同时执行,就会有大量的磁盘写入操作,不可取。
-
-
-
创建RDB文件 : 创建的工作由
rdbSave
函数完成。save和bgsave会以不用的方式调用这个函数。 -
rdb文件的载入 : 是在服务器启动时自动执行的,所以redis中没有载入rdb文件的命令,只要redis服务器在启动时检测到rdb文件存在,就会自动载入rdb文件。载入RDB的工作由
rdbLoad
函数完成。服务器载入RDB文件期间,会一直处于阻塞状态,直到载入完成为止。
-
AOF文件的更新频率比RDB文件的更新频率高,
- 如果服务器开启了AOF持久化,服务器会优先使用AOF来还原数据库状态
- 只有AOF持久化功能关闭,服务器才会使用RDB来还原数据库状态
2. 自动间隔性保存
-
因为bgsave不会阻塞服务器,所以redis允许让服务器每隔一段时间自动执行一次bgsave命令。用户可以设置多个保存条件,只要其中一个被满足,服务器就会执行bgsave。
-
设置保存条件:用户可以通过配置文件或者传入启动参数的方法设置save选项,如果用户没有设置save选项,服务器会采用默认条件:
save 900 1 : 90s内至少对数据库修改1次 save 300 10 : 300s内至少对数据库修改10次 save 60 10000 :60s内至少对数据库修改10000次
接着,根据save选项,设置redisServer的saveparams属性。saveparams是一个数组,数组中的每个元素都是一个saveparams结构,每个saveparams结构都保存了一个save选项设置的保存条件,比如默认条件的数组:
-
dirty计数器和lastsave属性:
-
dirty计数器:记录距离上一次成功执行save命令或者bgsave命令后,服务器对数据库进行了多少次修改。比如,向一个集合键增加三个新元素,dirty的值增加3.
sadd database redis mongoDB mariaDB
-
lastsave:是个Unix时间戳,记录了服务器上一次成功执行save或者bgsave命令的时间。
-
-
检查保存条件是否满足
- 周期操作函数serverCron默认每隔100ms就会执行一次,函数其中一项任务就是检查save选项所设置的条件是否已经满足,如果满足,就执行bgsave。
3. RDB文件结构
-
文件结构如下:全大写:常量,全小写:变量和数据
-
文件最开头的5个字节,保存“REDIS”, 程序在载入文件时,可以快速检查所载入的文件是否是RDB文件。
-
db_version:4字节,整数,记录rdb文件的版本号,比如“0006”代表RDB文件的版本为第六版。
-
database:包含0个或者任意多个数据库,以及数据库中的键值对数据。如果所有数据库都是空的,那么这个部分也是空的,长度为0字节。如果数据库有值,这个部分也非空,根据数据库所保存键值对的数量、类型和内容不同,这部分的长度也会有所不同。
-
EOF:EOF常量的长度为1字节,标志RDB文件正文内容的介绍,读入到这个值时,就知道所有键值对都已经载入完毕了。
-
check_sum:8字节长的无符号整数,保存校验和,校验和通过对前四个部分的内容进行计算得出的。服务器载入RDB文件时,会将载入数据计算出的校验和和check_sum所记录的校验和进行对比,以此来检查rdb文件是否出错或者损坏。
-
举个栗子:
-
database部分:database部分可以保存任意多个非空数据库。举个栗子:
每个非空数据库在RDB中都保存为:SELECTDB、db_number、key_value_paris- SELECTDB: 1字节,当读入程序遇到这个值时,就知道接下来要读入的是一个数据库号码
- db_number:数据库号码,根据号码的不同,长度也不同,1字节、2字节、5字节。当读入这部分之后服务器就调用select,进行数据库切换。
- key_value_paris:保存数据库中的所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在一起。
-
key_value_paris部分:
-
rdb中每个key_value_paris部分都保存了一个或以上数量的键值对,如果键值对带有过期时间,也会一起保存在内。
-
不带过期时间的键值对由type、key、value组成。
- type:记录了value的类型,1字节
- key:键,编码方式:redis_rdb_type_string
-
带过期时间的键值对:expiretime_ms、ms、type、key、value
- expiretime_ms:1字节,告知读入程序,接下来要读入的是一个以毫秒级为单位的过期时间
- ms:8字节长的带符号整数,一个以毫秒为单位的Unix时间戳,就是键值对的过期时间。
-
举个栗子:
-
-
value的编码:
- 字符串对象:P144