暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

《Redis设计与实现》读书笔记(十四) ——Redis RDB文件创建、载入与自动保存原理

爱思考的coder 2017-09-04
439

《Redis设计与实现》读书笔记(十四) 

——Redis RDB文件创建、载入与自动保存原理

(原创内容,转载请注明来源,谢谢)


一、概述

         redis是一个键值对服务器,服务器中包含若干个非空数据库,数据库中包含若干个非空键值对。将非空数据库及其键值对统称为数据库状态。如下图所示:


         由于redis是内存型数据库,必须要将数据保存到磁盘,才能保证数据不丢失。RDB持久化就是将数据库保存到磁盘的方式之一(另一种叫做AOF)。rdb可以手动执行,也可以根据服务器的配置定期执行,持久化后会将整个数据库备份成一个二进制文件存在磁盘,而还原则是将该二进制文件重新转成数据库存在内存。

 

二、rdb文件创建与载入

1、创建

         有两个命令可以手动生成rdb文件——savebgsave

         save会阻塞redis进程,直到save命令执行完毕;bgsave会创建一个子进程,由子进程处理rdb任务,父进程继续处理客户端请求。

         保存rdb文件的过程,如果是bgsave命令,会先检查是否当前有还未完成的子进程,如果有的话会等待,待当前子进程完成任务后,才会开始执行bgsave

1save

         由于save命令是阻塞的,因此当执行save命令期间,服务器会拒绝其他命令的请求,直到save命令执行完毕。

2bgsave

         bgsave是通过子进程进行创建rdb文件的工作,因此bgsave执行期间,服务器可以正常处理大部分的redis客户端请求,除了以下内容有所不同

         saveredis子进程在处理bgsave命令期间,会拒绝客户端发来的save命令,目的是为了避免父进程和子进程同时在创建rdb文件,也避免产生竞争条件。

         bgsave:同样会被拒绝,同save

         bgwriteaofbgsave执行期间,bgwriteaof命令会被延迟到bgsave命令执行完毕后才会执行; bgwriteaof执行期间,bgsave命令会直接被服务器拒绝。这两个命令都是由子进程进行,拒绝同时进行是为了考虑性能,并发处理两个大量写入磁盘的子进程是应当被避免的。

 

2、载入

         载入比较简单,redis没有专门载入rdb文件的命令,每当redis服务器开启的时候,就会检查,如果存在rdb文件则自动载入。

         但是由于aof的执行频率比rdb高,所以如果同时存在aof文件,则会载入aof文件,只有aof功能除以关闭状态,才会载入rdb文件。

         redis服务器载入rdb文件期间,会一直处于阻塞状态,直到载入完毕。

         如下所示:


三、自动保存

         由于bgsave命令具有非阻塞特性,因此redis服务器运行用户通过配置文件中的save选项,让数据库每隔一段时间执行一次bgsave命令。save选项保存的是执行bgsave命令的条件,可以保存多个,只要有一个条件满足,服务器就执行bgsave命令。

         save设置的示例如下:

         save900 1

         save300 10

         save60 10000

         表示的含义是,下列情况发生一种就执行bgsaveredis服务器900秒内至少执行1次修改;300秒内至少执行10次修改;60秒内至少执行10000次修改。

         上述的save条件也是redis配置save的默认值,即没有特意指定save条件,则都会按上述设置执行bgsave

1、保存结构

         服务器启动时,会读取save条件,并写入其redisServer结构的saveparams属性中。

         structredisServer{

         //…其他属性

         struct saveparam *saveparams;

}

由上可知,saveparams是一个数组,由saveparam结构元素组成。

         structsaveparam{

         time_t seconds;

         int changes;

}

由上结构可知,saveparam保存了时间和改变次数,即对应上述每一行save后面跟的两个参数。

上面默认的save条件配置的存储方式如下图所示:

 

2dirty计数器和lastsave属性

         dirty计数器记录距离上一次成功执行savebgsave命令后,服务器对其中所有数据库进行的修改(增删改)的总次数。lastsave属性是一个UNIX时间戳,记录服务器上一次成功执行savebgsave的时间。

         structredisServer{

         long long dirty;

         time_t lastsave;

}

结构如下图所示:


每执行一次修改,dirty值就加1,如果是批量修改命令如sadd等,一次修改多个值,则修改几个dirty的值就加多少。

这两个属性分别是用于比较save条件的两个参数——修改次数和时间,是否匹配,以判定是否要执行bgsave命令。

 

3、检查是否满足保存条件

         redis服务器的周期性函数serverCron,默认每隔100毫秒执行一次,用来维护运行中的服务器,其中一项工作就是检查save条件,满足的话就执行bgsave命令。

         其判断方式是,循环save配置,分别比较save每一条配置的修改次数与redisServer结构中的dirty属性值、当前时间减去lastsave属性判断经过的时间,有一个符合则执行bgsave命令。

         总体结构体如下:


         上述情况来看,dirty123,则当时间经过300秒,就会自动执行bgsave

         执行完成后,dirty属性值清0,并且lastsave属性会被重新写入完成bgsave时间点的unix时间戳。



——written by linhxx 2017.09.04

文章转载自爱思考的coder,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论