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文件。
![](https://img-blog.csdn.net/20171023210824876?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
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命令。
上述的配置在第一节中出现过;
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
执行save命令时,只能发现一句话,不是子进程打印出来的,没有提示是background save。
5490:M 24 Oct 09:50:39.190 * DB saved on diskredis的保存条件
![](https://img-blog.csdn.net/20171024103201952?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
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命令的时间
假设原有记录如下:
![](https://img-blog.csdn.net/20171024104907901?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
当执行完一次BGSAVE之后,
![](https://img-blog.csdn.net/20171024104943534?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
redisRDB的文件结构
常量是大写,小写是变量和数据,
可以看见开头是REDIS固定常量。
然后时db的版本,
接着是哪一个数据库,
然后时EOF结尾,
最后是一个校验数字,校验数字是一个8字节无符号的整数,是前4个内容进行计算得出,当载入RDB时,会进行比较,以确定没有损坏。
![](https://img-blog.csdn.net/20171024134552788?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
database
redis默认有16个数据库,那么这边最多可能存储16个数据库的数据,下图展示 了0和3号数据库存在非空数据
![](https://img-blog.csdn.net/20171024135835288?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
而database的结构由是由下面的组成:
![](https://img-blog.csdn.net/20171024143150404?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
SELECTDB是常量,表明需要执行select语句,以保证数据进入对应的数据库中去。
db_number: database的不同库
key_value_pairs:故名意思了,键值对。
![](https://img-blog.csdn.net/20171024143350514?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
key_value部分
![](https://img-blog.csdn.net/20171024143709672?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
不带过期时间的结构
TYPE:每个type常量都代表了一种对象类型或者底层编码,当需要读入RDB文件的键值对时,程序会根据TYPE的值来决定如何读入和解释value的数据。
key和value不去解释了。
带有过期时间的结构如下:
会带有EXPIRETIME_MS常量,表明程序将读入一个以毫秒为单位的过期时间
ms:8字节的带符号整数,以毫秒为单位的UNIX的时间戳.
![](https://img-blog.csdn.net/20171024143955827?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI5MjQzNDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
具体的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>
\0:数据库是database0
003:第一个键的长度是3-->abc
006:值的长度是6,Im a p。
数字型的暂时没看懂是存的啥...
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。
数字型的暂时没看懂是存的啥...
相关文章推荐
- redis学习系列(四)--redis的RDB持久化配置以及数据恢复实验
- redis学习系列(六)--redis基础跳跃表的构造
- redis学习系列(九)--redis-AOF和RDB实践
- redis学习系列(四)--redis基础SDS的构造
- redis学习系列(三-1)--redis基础类型初探(字符串)
- redis学习系列(三-2)--redis基础类型初探(列表对象)
- redis学习系列(三-3)--redis基础类型初探(hash对象)
- redis学习系列(七)--redis-database
- 八、Redis 基础命令---管理--持久化--RDB
- Redis学习系列(一):Redis服务器端的配置与启动
- redis学习系列--2.redis-string类型
- Redis学习系列——Redis安装
- SpringBoot系列: Redis基础
- redis学习系列(一)--redis主从,哨兵,集群
- redis学习系列(十二)--redis-锁的实现
- redis学习系列(十一)--redis-复制功能实践
- redis系列:RDB持久化与AOF持久化
- REDIS学习(6)查看redis状态,以及rdb和aof两种持久化方案的区别
- redis学习系列(二)--spring boot整合Redis集群
- redis学习系列(五)--redis基础字典的构造