1.介绍
1.1什么是数据库状态
Redis是一个键值对数据库服务器,服务器中包含任意个非空数据库,而每个非空数据库中又包含任意个键值对,为了方便起见我们将服务器中的非空数据库以及他们的键值对统称为数据库状态。
1.2为什么要进行持久化?
Redis是内存数据库,它的数据都保存在内存中,所以如果不将内存中的数据保存到磁盘中,那么一旦Redis进程退出,那么内存中保存的数据也会丢失,所以Redis提供了RDB持久化功能。
1.3什么是RDB?
RDB是Redis提供的持久化功能,这个功能可以将Redis在内存中的数据库状态保存到磁盘中,避免数据以外丢失。RDB可以进行手动执行也可以根据服务器配置定期执行,这个功能可以将某个时间点上的数据保存到一个RDB文件中。
RDB持久化生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据。
2.RDB文件的创建和载入
2.1使用方法
有两个Redis命令可以用于生成RDB文件,一个是SAVE,另一个是BGSAVE。
-
SAVE命令:SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。
redis>SAVE //等待RDB文件创建完毕 OK
伪代码如下:
def SAVE(): #创建RDB文件 rdbSave();
-
BGSAVE命令:BGSAVE命令跟SAVE命令做法不同,BGSAVE会派生一个子进程,然后由子进程负责创建RDB文件,服务器进程会继续处理命令请求。
redis>BGSAVE //派生子进程,并由子进程创建RDB文件 Background saving started
伪代码如下:
def BGSAVE(): #创建子进程 pid = fork(); if pid == 0; #子进程负责创建RDB文件 rdbSave(); #完成之后向父进程发送信号 signal_parent(); elif pid>0: #父进程继续处理命令请求,并通过轮询等待子进程的信号 hadle_request_and_wait_signal(); else: //处理出错情况 handle_fork_error;
2.2 载入
和SAVE命令或者BGSAVE命令不同的是,RDB文件的载入工作是在服务器启动时自动执行的,Redis并没有专门用于载入RDB文件的命令,只要Redis服务器启动时检测到RDB文件,它就会自动载入RDB文件。
因为AOF文件的更新频率通常比RDB文件的更新频率高,所以:
如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据。
只有在AOF持久化功能处于关闭状态,服务器才会使用RDB文件来还原数据。
服务器还原数据流程图如下:
2.3 SAVE命令执行时的服务器状态:
SAVE命令执行时,Redis服务器会被阻塞,所以当SAVE命令正在执行时,客户端发送的所有命令都会被阻塞。只有在服务器执行完SAVE命令,重新开始接收命令请求之后,客户端发送的命令才会被处理。
SAVE命令执行时的服务器状态
2.4 BGSAVE命令执行时的服务器状态:
因为BGSAVE命令的保存工作是由子进程执行的,所以子进程创建RDB文件的过程中,Redis服务器任然可以继续处理命令请求,但是服务器在处理SAVE、BGSAVE、BGREWRITEAOF三个命令的方式会跟平时不同:
- 在BGSAVE命令执行期间,客户端发送的SAVE命令会被服务器拒绝执行,服务器禁止SAVE命令和BGSAVE命令同时执行是为了避免父进程(服务器进程)和子进程同时执行rdbSave调用,防止产生竞争条件。
- BGSAVE执行期间,客户端发送的BGSAVE命令也会被服务器拒绝,因为同时执行两个BGSAVE命令也会产生竞争条件。
- BGSAVE命令和BGREWRITEAOF命令不能同时执行:
- 如果BGSAVE命令正在执行,客户端发送的BGREWRITEAOF命令会被延迟到BGSAVE命令执行完毕之后执行。
- 如果BGREWRITEAOF命令正在执行,那么客户端发送的BGSAVE命令会被服务器拒绝。
这是因为BGSAVE和BGREWRITEAOF两个命令的实际工作都是由子进程执行,两个子进程都同时执行大量磁盘写入操作会造成性能问题。