《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 条评论
登录 后参与评论

相关文章

来自专栏源码之家

linux下用wget命令下载整个ftp下目录及目录下所有文件和Bad port number错误的解决方法

1404
来自专栏Java成神之路

Struts框架搭建时所遇到的问题

        解决方案:将以下7个jar拷贝到项目工程中_(workspace_项目名_webRoot_WEB-INF_lib下),其他用到的包再慢慢添加: ...

755
来自专栏Java帮帮-微信公众号-技术文章全总结

操作Linux这些命令够用了

操作Linux这些命令够用了 玩过Linux的人都会知道,Linux中的命令的确是非常多,但是玩过Linux的人也从来不会因为Linux的命令如此之多而烦恼,因...

4196
来自专栏xingoo, 一个梦想做发明家的程序员

程序猿的日常——工作中常用的Shell脚本

如果目录下的文件很多,无法直接rm -rf,那么可以寻找一些匹配模型,分批删除。比如文件下面有很多的文件:

1282
来自专栏Python爬虫实战

秒懂python编程中的if __name__ == '__main__'

相信初学者在学习Python的过程中,不可避免的总会遇到if __name__ == '__main__'语句,虽然一直知道它的作用,但是可能一直比较模糊,今天...

801
来自专栏帅小子的日常

JVM内存管理

1243
来自专栏性能与架构

nginx 缓存机制

Nginx缓存的基本思路 利用请求的局部性原理,将请求过的内容在本地建立一个副本,下次访问时不再连接到后端服务器,直接响应本地内容 Nginx服务器启动后,会对...

5406
来自专栏蓝天

通用的进程监控重拉起bash脚本process_monitor.sh

671
来自专栏别先生

mysql输入密码后闪退怎么办?

第一: 首先需要想到的是mysql的服务可能没开,首先打开mysql的服务 ? 第二: 打开Mysql的命令行输入密码即可 ? 第三: 登录成功 ? 第四: 顺...

2289
来自专栏java思维导图

【一分钟知识】线程同步,线程调度

sleep()和yield()方法区别 1 sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会; yield()方法只...

3358

扫码关注云+社区