Redis 专题二: RDB 与 AOF 持久化

来源:互联网 发布:医疗器械软件研究 编辑:程序博客网 时间:2024/05/17 13:46

服务器中的数据库

  • Redis服务器将所有数据库都保存在服务器状态结构的db数组中,db数组的每个项都是一个RedisDb结构,一个RedisDb结构数组的长度就代表了数据库的个数。默认情况下Redis的目标数据库是0号数据库,但客户端可以通过执行SELECT命令来切换数据库
    这里写图片描述
    在服务器内部,客户端状态redisClient结构的db属性记录了客户端当前的目标数据库,这个属性是一个指向RedisDb的指针
typedef struct redisClient{    //...    //记录客户端当前正在使用的数据库    redisDb *db;} redisClient;db[0],db[1],db[2],db[n]客户端通过改变redisClient.db的指针,让它指向服务器中的不同数据库,从而实现切换目标数据库的功能。这就是SELECT实现的原理struct redisServer{    //...    //一个数组,保存着服务器中的所有数据库    reddisDb *db;    //服务器的数据库数量    int dbnum;    //...}db[0],db[1],db[2],db[n]

持久化

RDB

  • 因为Redis是内存数据库,它将自己的数据库状态存储在内存里面。所以如果不即使的把存放在内存里的数据写入到磁盘,那么一旦服务器宕机数据将全部消失。”持久化”呼之欲出,持久化的实质是将数据写到磁盘,保证数据”持久”可用。

  • 为什么把数据放内存? 这就是Redis与其它关系型数据库的区别,虽然关系型数据库(例如:mysql)也有把部分数据放入到内存,但是仅仅是部分,为了提高缓存命中率mysql会把常用数据放到内存里(buffer cache),这样就可以尽量多的减少数据库去磁盘读取数据的次数,因为在一次物理I/O中,磁盘寻道占据了读取数据所用总时间的绝大一部分,我们想让更多的读写都是逻辑I/O(内存读写)而不是物理I/O。所以Redis的特性适合高频率,高速读写的业务。

    • RDB :
      RDB持久化可以在指定的时间间隔内生成数据的时间点快照

    • 创建新的RDB文件:
      在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB文件中。SAVE命令和BGSAVE命令会以不同的方式调用这个函数。对于SAVE命令来说,Redis会调用rdbSave()函数来创建RDB文件,这个过程是阻塞的,在rdbSave()命令执行期间Redis服务器将无法相应客户端的请求,而对于BGSAVE命令来说,它会先调用fork()创建一个子进程,然后再子进程中去执行rdbSave()函数,这样就不会对主进程造成阻塞

    • 载入RDB:
      和使用SAVE,BGSAVE命令创建RDB文件不同,RDB文件的载入工作是在服务器启动时自动执行的,所以Redis并没有专门用于载入RDB文件的命令,只要Redis服务器在启动时检测到RDB文件的存在,它就会自动载入RDB文件。
      另外值得一提的是,因为AOF文件的更新频率通常比RDB文件的更新频率要高,所以:
      1: 如果服务器开起了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态
      2:只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态。
  • BGSAVE命令
    因为BGSAVE命令的保存工作是由子进程执行的,所以在子进程创建RDB文件的过程中,Redis服务器仍然可以继续处理客户端的命令请求,但是,在BGSAVE命令执行期间,服务器处理SAVE,BGSAVE,BGREWRITEAOF三个命令的方式会和平时有所不同。
    首先,在BGSAVE命令执行期间,客户端发送的SAVE命令会被服务器拒绝,服务器禁止SAVE命令和BGSAVE命令同时执行是为了避免父进程(服务器进程)和紫禁城同时执行两个rdbSave调用,防止产生竞争条件。
    其次,在BGSAVE命令执行期间,酷护短发送的BGSAVE命令会被服务器拒绝,因为同时执行两个BGSAVE命令也会产生竞争条件
    最后,BGREWRITEAOF和BGSAVE两个命令不能同时执行:
    1 . 如果BGSAVE命令正在执行,那么客户端发送的GBREWRITEAOF命令会被延迟到BGSAVE命令执行完毕之后执行
    2 . 如果BGREWRITEAOF命令正在执行,那么客户端发送的BGSAVE命令会被服务器拒绝
    因为BGREWRITEAOF和BGSAVE两个命令的实际工作都是由子进程执行的,所以这两个命令在操作方面并没有什么冲突的地方,不能同时执行它们只是一个性能方面的考虑,并发出两个子进程,并且这两个子进程都同时执行大量的磁盘写入操作,这怎么想都不是一个好主意。

  • 自动隔时性保存
    以为BGSAVE命令可以在不阻塞服务器的情况下执行,所以Redis允许用户通过设置服务器配置的SAVE选项,让服务器每隔一段时间自动执行一次BGSAVE命令,用户可以通过SAVE选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE命令。
    当准备启动Redis服务器时,用户可以通过指定配置文件或者传入启动参数的方式设置save选项,如果用户没有主动设置save选项,那么服务器会为save选项设置一个默认条件,接着,服务器程序会根据save选项所设置的保存条件,设置服务器状态redisServer结构的saveparams属性:

    struct redisServer{     //记录了保存条件的数组     struct saveparams *saveparams;}saveparam 属性是一个数组,数组中的每个元素都是一个saveparam的结构,每个saveparam结构都保存一个save选项设置的保存条件:struct saveparams{     //秒数     time_t seconds;     //修改数     int changes;}比如说,如果save选项的值为以下条件save 900 1save 300 10save 60 10000表示如果900秒内有超过1次的数据库修改操作就执行rdbsave函数,如果300秒内有超过10次的数据库修改操作就执行rdbsave函数,如果60秒内有超过10000次的数据库修改操作就执行rdbsave函数
  • dirty 计数器和lastsave属性
    除了saveparams数组之外,服务器状态还维持一个dirty计数器,以及一个lastsave属性:

    • dirty计数器记录距离上一次成功执行SAVE命令或者BGSAVE命令之后,服务器对数据库状态进行了多少次修改(写入,删除,更改)
    • lastsave属性是一个unix时间戳,记录了服务器上一次成功执行SAVE命令或者BGSAVE命令的时间。
      当服务器成功执行一个数据库修改命令之后,程序就会对dirty计数器进行更新:命令修改了多少次数据库,dirty计数器的值就增加多少。
  • RDB文件结构
    这里写图片描述
    db_version:
    长度为4字节,它的值是一个字符串表示的整数。这个整数记录了RDB文件的版本号。

    EOF:
    长度是1字节的常量,这个常量标志着RDB文件正文内容的结束,当读入程序通过REDIS,db_version,databases,EOF这四个部分的内容进行计算得出的,服务器在载入RDB文件时,会将载入数据所计算出的校验和与check_sum所记录的校验和进行对比,以此来检查RDB文件是否有出错或者损坏的情况出现。

    SELECTDB:
    长度为1字节的常量,当读入程序遇到这个值的时候,它知道接下来要读入的将是一个数据库号码

    db_number:
    保存着一个数据库号码,根据号码的大小不同,这个部分的长度可以是1个字节,2个字节,或者是5个字节,当程序读入db_number部分后,服务器会调用SELECT命令,根据读入的数据库号码进行数据库切换,使得之后读入的键值对可以载入到正确的数据库中。

    key_value_pairs:
    部分保存了数据库中的所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在一起,根据键值对的数量,类型,内容以及是否有过期时间条件的不同,key_value_paris部分的长度也会有所不同。

    expiretime_ms:
    是一个长度为1字节的常量,它告知读入程序,接下来要读入的将是一个以毫秒为单位的过期时间

    ms:
    是一个8字节长的带符号整数,记录着一个以毫秒为单位的unix的时间戳,这个时间戳就是键值对的过期时间

    REDIS_RDB_ENC_LZF:
    标志着字符串已经被LZF算法压缩过了,读入程序在碰到这个变量时,会根据之后的compressed_len,origin_len和compressed_string三部分,对字符串进行压缩:其中compressed_len记录的是字符串被压缩之后的长度,而origin_len记录的是字符串原来的长度,compressed_string记录的则是被压缩之后的字符串。

  • RDB总结:

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

AOF

0 0
原创粉丝点击