Redis(设计与实现):23---RDB持久化之自动间隔性保存(save选项、struct saveparam、dirty属性、lastsave属性)

一、自动间隔性保存介绍(save选项)

  • 前面一篇文章介绍了SAVE、BGSAVE命令,其中BGSAVE命令可以在不阻塞服务器进程的情况下执行,所以Redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令

save选项的格式

  • 用户可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE命令
  • 如果用户没有主动设置save选项,那么服务器会为save选项设置默认条件:

  • 上图的意思是,只要满足以上三个条件中的任意一个,BGSAVE命令就会被执行:
    • 服务器在900秒之内,对数据库进行了至少1次修改
    • 服务器在300秒之内,对数据库进行了至少10次修改
    • 服务器在60秒之内,对数据库进行了至少10000次修改
  • 举个例子,以下是Redis服务器在60秒之内,对数据库进行了至少10000次修改之后,服务器自动执行BGSAVE命令时打印出来的日志:

二、save选项的保存(struct saveparam)

  • 当Redis服务器启动时,用户可以通过指定配置文件或者传入启动参数的方式设置save选项。服务器程序会根据save选项所设置的保存条件,设置服务器状态redisServer结构的saveparams属性。saveparams属性是一个数组,数组中的每个元素都是一个saveparam结构,每个saveparam结构都保存了一个save选项设置的保存条件:
struct redisServer {
    // ...
    struct saveparam *saveparams;//记录了save保存条件的数组
    // ...
};
struct saveparam {
    time_t seconds;//秒数
    int changes;//修改数
};

图示

  • 比如说,如果save选项的值为以下条件:
save 900 1
save 300 10
save 60 10000
  •  那么服务器状态中的saveparams数组将会是下图所示的样子

Redis(设计与实现):23---RDB持久化之自动间隔性保存(save选项、struct saveparam、dirty属性、lastsave属性)_第1张图片

三、dirty计数器和lastsave属性

struct redisServer {
    // ...
    long long dirty;//修改计数器
    time_t lastsave;//上一次执行保存的时间
    // ...
};
  • 除了saveparams数组之外,服务器状态还维持着一个dirty计数器,以及一个lastsave属性:
    • dirty计数器记录距离上一次成功执行SAVE命令或者BGSAVE命令之后,服务器对数据库状态(服务器中的所有数据库)进行了多少次修改(包括写入、删除、更新等操作)
    • lastsave属性是一个UNIX时间戳,记录了服务器上一次成功执行SAVE命令或者BGSAVE命令的时间
  • 当服务器成功执行一个数据库修改命令之后,程序就会对dirty计数器进行更新:命令修改了多少次数据库,dirty计数器的值就增加多少。例如,我们向一个集合键增加3个新元素,那么dirty计数器的值增加3
SADD database Redis MongoDB MariaDB

图示

  • 下图展示了服务器状态中包含的dirty计数器和lastsave属性,说明如下:
    • dirty计数器的值为123,表示服务器在上次保存RDB文件内容之后,对数据库状态共进行了123次修改
    • lastsave属性则记录了服务器上次执行保存操作的时间1378270800(2013年9月4日零时)

Redis(设计与实现):23---RDB持久化之自动间隔性保存(save选项、struct saveparam、dirty属性、lastsave属性)_第2张图片

四、检查save选项是否满足(serverCron函数

  • Redis的服务器周期性操作函数serverCron默认每隔100毫秒就会执行一次,该函数用于对正在运行的服务器进行维护,它的其中一项工作就是检查save选项所设置的保存条件是否已经满足,如果满足的话,就执行BGSAVE命令
  • 以下伪代码展示了serverCron函数检查保存条件的过程:
    • 程序会遍历并检查saveparams数组中的所有保存条件,只要有任意一个条件被满足,那 么服务器就会执行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()
    # ...

演示案例:

  • 举个例子,如果Redis服务器的当前状态如下图所示

Redis(设计与实现):23---RDB持久化之自动间隔性保存(save选项、struct saveparam、dirty属性、lastsave属性)_第3张图片

  • 那么当时间来到1378271101,也即是1378270800的301秒之后,服务器将自动执行一次BGSAVE命令,因为saveparams数组的第二个保存条件——300秒之内有至少10次修改——已经被满足
  • 假设BGSAVE在执行5秒之后完成,那么上图所示的服务器状态将更新为下图所示,其中dirty计数器已经被重置为0,而lastsave属性也被更新为1378271106

Redis(设计与实现):23---RDB持久化之自动间隔性保存(save选项、struct saveparam、dirty属性、lastsave属性)_第4张图片

你可能感兴趣的:(Redis(设计与实现))