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

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

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

一、概述

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

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

二、rdb文件创建与载入

1、创建

有两个命令可以手动生成rdb文件——save和bgsave。

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

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

1)save

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

2)bgsave

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

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

bgsave:同样会被拒绝,同save。

bgwriteaof:bgsave执行期间,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

表示的含义是,下列情况发生一种就执行bgsave:redis服务器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条件配置的存储方式如下图所示:

2、dirty计数器和lastsave属性

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

         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命令。

总体结构体如下:

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

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

——written by linhxx 2017.09.04

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-09-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我是业余自学C/C++的

C++中的文件和流

1074
来自专栏小樱的经验随笔

【批处理学习笔记】第二十六课:返回值

    有些命令在执行之后将会返回一定的错误值(errorlevel),可以通过errorlevel的值判断命令执行的状况。这点类似于C语言里面的exit(nu...

2696

Docker in action: 共享内存命名空间

本文摘自“ Docker in Action ”一书,在此文中,我将向您展示如何打开对容器之间共享内存的访问。

1939
来自专栏开源优测

python selenium2示例 - 日志管理

前言 在自动化测试实践过程中,必不可少的就是进行日志管理,方便调试和生产问题追踪,python提供了logging模块来进行日志的管理。下面我们就...

3244
来自专栏禁心尽力

MySQL日志文件之错误日志和慢查询日志详解

MySQL数据库官方文档:https://dev.mysql.com/doc/refman/5.7/en/server-logs.html 一、MySQL日志分...

2148
来自专栏linux驱动个人学习

VFS四大对象之二 struct inode

继上一篇文章:https://cloud.tencent.com/developer/article/1053842 二、inode结构体:(转自http://...

4627
来自专栏云计算

Docker in Action:共享内存命名空间

摘自“Docker in Action”一书,在本文中,我将展示如何在容器之间共享内存空间。

2345
来自专栏友弟技术工作室

bash脚本编程

1293
来自专栏地方网络工作室的专栏

Shell 从日志文件中选择时间段内的日志输出到另一个文件

Shell 从日志文件中选择时间段内的日志输出到另一个文件 情况是这样的,某系统的日志全部写在一个日志文件内,所以这个文件非常大,非常长,每次查阅的时候非常的不...

1598
来自专栏北京马哥教育

LVM详解

petmaster出品 必是精品 一、概述 LVM全称为Logical Volume Manager,即逻辑卷管理器。LVM可以弹性的调整文件系统的容...

2539

扫码关注云+社区