您的位置:首页 > 数据库 > Redis

redis学习系列(八)--redis-RDB基础

2017-10-23 20:57 1021 查看
RDB是一种持久化的概念,本身redis是一款内存数据库,速度很快,但是如果哪天突然宕机了,那么数据就会丢失掉,基于此,redis提供了RDB持久化功能,可以将redis在内存中的数据持久化到磁盘,避免丢失。

RDB可以手动执行,也可以设置定期执行,将内存中的数据库状态保存到磁盘里。

反之,可以通过该文件还原生成RDB时的数据库状态。

RDB文件的创建和载入

两个命令生成RDB文件,SAVE和BGSAVE

SAVE:阻塞Redis服务器进程,直到RDB文件创建完毕,当服务器进程阻塞期间,服务器不能处理任何命令请求

BGSAVE:派生出子进程,然后负责创建RDB文件,父进程继续处理命令请求

RDB文件的载入是在服务器启动时自动执行,所以Redis没有专门载入RDB文件的命令,只要Redis服务器再启动时检测到RDB文件存在,就会自动载入RDB文件。



BGSAVE处理时的服务器状态

BGSAVE处理由于是子进程,所以客户端请求能正常处理,但是也有特别,有三种命令不能同时执行。

SAVE;BGSAVE;BGREWRITEAOF;

SAVE不能执行的原因大概就是因为多线程,多线程下会产生竞态条件,这个术语在并发编程经常遇到,多线程本身实现的不好会带来意想不到的问题,我觉得这边不让父线程和子线程同时执行,有可能就是再避免使用多线程吧。

BGSAVE不能执行也是同样如此。

BGREWRITEAOF不能执行的原因书中的观点是只是性能方面的考虑,因为两个子线程同时进行大量的IO操作不是一个很明智的选择。

RDB文件载入时的服务器状态

载入时,Redis都是处于阻塞状态的,直到载入完成为止。

4282:M 24 Oct 08:54:49.736 * DB loaded from disk: 0.011 seconds
4282:M 24 Oct 08:54:49.736 * The server is now ready to accept connections on port 6379
这边可以看见DB loaded就是在读取RDB文件。试着把RDB文件删除掉,本机测试数据在里面,无碍。

可以看见下面加载没有加载文件信息

4775:M 24 Oct 09:03:50.304 * The server is now ready to accept connections on port 6379
自动间歇性保存

Redis可以设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令。

save 900 1
save 300 10
save 60 10000


上述的配置在第一节中出现过;

900s之内,对数据库进行了至少一次修改;

300s之内,对数据库进行了至少10此修改;

60s之内,对数据库进行了至少10000次修改;

这边有点奇怪,我昨天进行上面database的测试时发现redis自动进行过RDB的备份,但是今天是执行了20此set操作,等了大概10分钟,也没有进行自动备份,然后我手动执行了一下备份。奇怪,不了解呢,,,,bgsave下之后客户端发现打印出了备份信息,dump.rdb文件里也存在了,但是10分钟它不执行是几个意思???

5490:M 24 Oct 09:46:38.411 * Background saving started by pid 5934
5934:C 24 Oct 09:46:38.414 * DB saved on disk
5934:C 24 Oct 09:46:38.414 * RDB: 0 MB of memory used by copy-on-write
5490:M 24 Oct 09:46:38.466 * Background saving terminated with success
]$ cat dump.rdb
REDIS0006�num2�
num1
�Q����H�[@localhost bin]$ cat dump.rdb
REDIS0006�num6num15�num16�num14�num9�num7�num10�num3�
num5num1                                                     num4
num8�num2�
num12�num13�num17�num11��\2


执行save命令时,只能发现一句话,不是子进程打印出来的,没有提示是background save。
5490:M 24 Oct 09:50:39.190 * DB saved on diskredis的保存条件
struct redisServer {
struct saveparam *saveparams;   /* Save points array for RDB */
}
保存条件也是记录在redisServer中的,是一串数组,



dirty计数器和lastsave属性

除了上面这个数组之外,服务器还维护着dirty和lastsave属性

struct redisServer {

long long dirty; /* Changes to DB from the last save */

time_t lastsave; /* Unix time of last successful save */
}

dirty属性:dirty计数器记录距离上一次成功执行SAVE命令或者BGSAVE命令之后,服务器对数据库状态进行了多少次修改。
lastsave属性是一个UNIX时间戳,记录服务器上一次成功执行SAVE命令或者BGSAVE命令的时间

假设原有记录如下:



当执行完一次BGSAVE之后,



redisRDB的文件结构

常量是大写,小写是变量和数据,

可以看见开头是REDIS固定常量。

然后时db的版本,

接着是哪一个数据库,

然后时EOF结尾,

最后是一个校验数字,校验数字是一个8字节无符号的整数,是前4个内容进行计算得出,当载入RDB时,会进行比较,以确定没有损坏。



database

redis默认有16个数据库,那么这边最多可能存储16个数据库的数据,下图展示 了0和3号数据库存在非空数据



而database的结构由是由下面的组成:



SELECTDB是常量,表明需要执行select语句,以保证数据进入对应的数据库中去。

db_number: database的不同库

key_value_pairs:故名意思了,键值对。



key_value部分



不带过期时间的结构

TYPE:每个type常量都代表了一种对象类型或者底层编码,当需要读入RDB文件的键值对时,程序会根据TYPE的值来决定如何读入和解释value的数据。

key和value不去解释了。

带有过期时间的结构如下:

会带有EXPIRETIME_MS常量,表明程序将读入一个以毫秒为单位的过期时间

ms:8字节的带符号整数,以毫秒为单位的UNIX的时间戳.



具体的TYPE个value是怎么样的对应关系,不去做讨论了,现阶段我的主要目标是了解redis,需要注意自己的条件,深刻的研究是基于熟悉的基础上。

分析RDB文件

1.空RDB文件

[root@localhost bin]# od -c dump.rdb
0000000 R E D I S 0 0 0 6 377 334 263 C 360 Z 334
0000020 362 V
0000022REDIS:常量
0006:版本号

377:EOF常量

校验和:334 263 C 360 Z 334

2.塞一个int值和String值

127.0.0.1:6379> set num 10086
OK
127.0.0.1:6379> get num
"10086"
127.0.0.1:6379> set abc "Im a p"
OK
127.0.0.1:6379> get abc
"Im a p"
127.0.0.1:6379>
[root@localhost bin]# od -c dump.rdb
0000000   R   E   D   I   S   0   0   0   6 376  \0  \0 003   a   b   c
0000020 006   I   m       a       p  \0 003   n   u   m 301   f   ' 377
0000040   q 033   . 024 374 271   e 325
0000050
我现在开的是30S至少一次修改就执行备份RDB文件。
\0:数据库是database0

003:第一个键的长度是3-->abc

006:值的长度是6,Im a p。

数字型的暂时没看懂是存的啥...































内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: