redis RDB 持久化

Redis 提供了RDB 持久化功能,这个功能可以将Redis 在内存中的数据库状态保存到磁盘里面,避免数据意外丢失,RDB 文件是保存在硬盘里面的。

0.RDB 文件结构

REDISdb_versiondatabasesEOFcheck_sum
  • db_version 长度为4 字节,它的值是一个字符串表示的整数,记录了RDB文件的版本号。
  • databases 部分包含着零个或任意多个数据库,以及各个数据库中的键值对数据:
  • EOF 常量的长度为1 字节,这个常量标志着ROB 文件正文内容的结束,当读人程序遇
  • 到这个值的时候,它知道所有数据库的所有键值对都已经载人完毕了。
  • check_sum 是一个8 字节长的无符号整数,,保存着一个校验和,这个校验和是程序通过对REDIS 、db version 、databases 、EOF 四个部分的内容进行计算得出的。服务器在载入ROB 文件时,会将载入数据所计算出的校验和与check sum 所记录的校验和进行对比,以此来检查RDB 文件是否有出错或者损坏的情况出现。

1.对于每一个databases i :

SELECTDBdb_numberkey_value_pairs
  • SELECTDB 常量的长度为1 字节,当读人程序遇到这个值的时候,它知道接下来要读人的将是一个数据库号码。
  • db_number 保存着一个数据库号码,根据号码的大小不同,这个部分的长度可以是1 字节、2 字节或者5 字节。当程序读人db_number 部分之后,服务器会调用SELECT命令,根据读人的数据库号码进行数据库切换,使得之后读入的键值对可以载入到正确的数据库中。
  • key_value_pairs 部分保存了数据库中的所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在一起。根据键值对的数量、类型、内容以及是否有过期时间等条件的不同, key_value_pairs 部分的长度也会有所不同。

2.key_value_pairs
1)不带过期时间的key_value_pairs:

TYPEkeyvalue

TYPE 记录了value 的类型,长度为1 字节,值可以是以下常量的其中一个:
REDIS RDB TYPE STR工NG
REDIS RDB TYPE LIST
REDIS RDB TYPE SET
REDIS RDB TYPE ZSET
REDIS ROB TYPE HASH
REDIS ROB TYPE L工ST ZIPLIST
REDIS RDB TYPE SET INTSET
REDIS ROB TYPE ZSET Z 工PLIST
REDIS RDB TYPE HASH ZIPLIST

  • 当服务器读入RDB文件中的键值对数据时,程序会根据TYPE 的值来决定如何读人和解释value 的数据。
  • 其中key 总是一个字符串对象,它的编码方式和阻P工S ROB TYPE STRING 类型的value 一样。根据内容长度的不同, key 的长度也会有所不同。
  • 根据TYPE 类型的不同,以及保存内容长度的不同,保存value 的结构和长度也有所不同,本节稍后会详细说明每种TYPE 类型的value 结构保存方式。

value 的编码:

2)带有过期时间的键值对

EXPIRETIME_MSmsTYPEkeyvalue
  • EXPIRETIME_MS 常量的长度为1 字节,它告知读人程序,接下来要读人的将是一个以毫秒为单位的过期时间。
  • ms 是一个8 字节长的带符号整数,记录着一个以毫秒为单位的UNIX 时间戳,这个时间戳就是键值对的过期时间。
1.RDB 文件的创建

创建RDB文件:SAVE、BGSAVE
1)SAVE 命令会阻塞Redis 服务器进程,直到RDB 文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。
2)BGSAVE 命令会派生出一个子进程,然后由子进程负责创建RDB 文件,服务器进程(父进程)继续处理命令请求:

def SAVE():
    #创建RDB 文件
    rdbSave ()
def BGSAVE():
    #创建子进程
    pid = fork()
    if pid == 0:
        #子进程负责创建RDB 文件
        rdbSave()
        #子进程完成之后向父进程发送信号
        signal_parent()
    elif pid > 0#父进程继续处理命令请求,并通过轮询等待子进程的信号
        handle_request_and_wait_signal()
    else:
        #处理出错情况
        handle fork error()

在BGSAVE 命令执行期间,客户端发送的SAVE、BGSAVE 命令会被服务器绝,防止产生竞争条件。另外,BGREWRITEAOF 和BGSAVE 两个命令不能同时执行。

  • 如果BGSAVE 命令正在执行,那么客户端发送的BGREWRITEAOF 命令会被延迟到BGSAVE 命令执行完毕之后执行。
  • 如果BGREWRITEAOF 命令正在执行,那么客户端发送的BGSA阳命令会被服务器
    拒绝。

BGREWRITEAOF 和BGSAVE 两个命令的实际工作都由子进程执行,所以这两个命令在操作方面并没有什么冲突的地方,不能同时执行它们只是一个性能方面的考虑一一并发出两个子进程,并且这两个子进程都同时执行大量的磁盘写人操作,这怎么想都不会是一个好主意。

2.RDB 文件的载入——rdbLoad 函数

RDB 文件的载人工作是在服务器启动时自动执行的,所以Redis 并没有专门用于载入RDB 文件的命令,只要Redis 服务器在启动时检测到ROB 文件存在,它就会自动载入RDB 文件。
服务器在载人RDB 文件期间,会一直处于阻塞状态,直到载入工作完成为止。
注意:
因为AOF 文件的更新频率通常比ROB 文件的更新频率高,所以:
如果服务器开启了AOF 持久化功能,那么服务器会优先使用AOF 文件来还原数据库状态。只有在AOF 持久化功能处于关闭状态时,服务器才会使用ROB 文件来还原数据库状态。

3.自动间隔性保存

用户可以通过save 选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE命令。

struct saveparam *saveparams;//saveparams数组
struct saveparam {
    //秒数
    time t seconds;
    //修改数
    int changes;
};

服务器状态还维持着1个dirty 计数器,以及1个last save 属性:
1)dirty 计数器记录距离上一次成功执行SAVE 命令或者BGSAVE 命令之后,服务器对数据库状态(服务器中的所有数据库)进行了多少次修改(包括写入、删除、更新等操作)。
2)last save 属性是一个UNIX 时间戳,记录了服务器上一次成功执行SAVE 命令或者BGSAVE 命令的时间。

struct redisServer {
    //修改计数器
    long long dirty;
    //上一次执行保存的时间
    time t lastsave;
};

周期性操作画数serverCron 默认每隔100 毫秒就会执行一次,该函数用于对正在运行的服务器进行维护,它的其中一项工作就是检查save 选项所设置的保存条件是否已经满足,如果满足的话,就执行BGSAVE 命令。

def serverCron():
    #遍历所有保存条件
    for saveparam in server.saveparams:
    #计算距离上次执行保存操作有多少秒
    save interval = unixtime now () - server, lastsave
    #如果数据库状态的修改次数超过条件所设置的次数
    #并且距离上次保存的时间超过条件所设置的时间
    #那么执行保存操作
    if server.dirty >= saveparam.changes and \
    save interval> saveparam.seconds:
    BGSAVE()
4.分析RDB 文件

对应EDB文件的结构来看:
$ od -ex dump.rdb

重点

  • RDB 文件用于保存和还原Redis 服务器所有数据库中的所有键值对数据。
  • SAVE命令由服务器进程直接执行保存操作,所以该命令会阻塞服务器。
  • BGSAVE令由子进程执行保存操作,所以该命令不会阻塞服务器。
  • 服务器状态中会保存所有用save 选项设置的保存条件,当任意一个保存条件被满足时,服务器会自动执行BGSAVE 命令。
  • RDB 文件是一个经过压缩的二进制文件,由多个部分组成。
  • 对于不同类型的键值对, RDB 文件会使用不同的方式来保存它们。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值