设为首页 加入收藏

TOP

Redis专题二:RDB与AOF持久化
2015-11-21 01:25:46 来源: 作者: 【 】 浏览:0
Tags:Redis 专题 RDB AOF 持久化
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]

持久化

因为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 1 save 300 10 save 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文件结构

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇数据库的检查约束check约束 下一篇MSSQL远程连接

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: