////////////////////////一些命令//////////////////////////////
SAVE、BGSAVE: 创建RDB文件,程序会对数据库中的键进行检查,已经过期的键不会被保存到新建的RDB文件中。
127.0.0.1:6379> save
OK
127.0.0.1:6379> bgsave
Background saving started
save --->会阻塞服务器进程
bgsave --->派生子进程,由子进程创建RDB文件,服务器进程继续处理命令请求
////////////////////////////////////////////////////////////////////
RDB 通过保存数据库中的键值对持久化
AOF (append only file)通过保存服务器所执行的写命令持久化
RDB持久化
Redis是一个键值对数据库服务器
Redis服务器包含--->任意个非空数据库
每个数据库包含--》任意个键值对
数据库状态:把服务器的非空数据库和他们的键值对称为数据库状态
Redis是内存数据库--》所以在数据库退出前需要把数据存到磁盘上!
RDB文件-->经过压缩的二进制文件,RDB文件是保存在硬盘里的
伪代码:
def Save():
rdbsave()
def BGSave():
pid = fork()
if pid==0:
//子进程负责创建RDB文件
rdbsave()
//完成后向父进程发送信号
signal_parent()
elif pid>0:
//父进程继续处理命令请求,并通过轮询等待子进程信号
handle_request_and_wait_signal()
else:
//处理出错情况
handle_fork_error()
服务器开启时,如果检测到了RDB文件--》自动载入
注意:AOF的更新频率比RDB高,如果服务器开启了AOF功能--》优先使用AOF来还原数据库状态
RDB文件结构:
REDIS:用于检测是否是RDB文件
db_version:版本号
database:包含任意个数据库以及键值对数据
EOF:标志中RDB正文内容的结束
check_sum:前四个部分的校验和
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SAVE
OK
打开dump.rdb文件
可以看到 REDIS 版本号:0006 EOF 校验和
添加键值 msg
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SET msg "hello"
OK
127.0.0.1:6379> SAVE
OK
再次打开dump.rdb文件:
AOF命令追加
struct redisServer
{
//AOF缓冲区
sds aof_buf;
};
服务器执行完一个写命令后,会以协议格式将命令追加到 aof_buf末尾
Redis服务器进程伪代码:
def eventLoop():
while True:
//处理文件时间,接收命令请求以及发送命令回复
//处理请求时可能会有新的内容被追加到aof_buf中
processFileEvents()
//处理时间事件
processTimeEvents()
//考虑是否要将aof_buf中的内容写入到AOF文件中
flushAppendOnlyFile()
AOF文件还原:
服务器创建一个伪客户端,执行AOF中的所有命令,从而恢复到服务器关闭之前的状态
AOF文件重写:
随着服务器运行时间增长,AOF文件会越来越大,AOF文件来进行数据还原的时间会越来越长
所以--》可以用一个新的包含更少指令的AOF文件,代替现有的AOF文件
比如客户端执行了以下命令:
127.0.0.1:6379> rpush list "A" "B"
(integer) 2
127.0.0.1:6379> rpush list "C"
(integer) 3
127.0.0.1:6379> rpush list "D" "E"
(integer) 5
127.0.0.1:6379> lpop list
"A"
127.0.0.1:6379> lpop list
"B"
127.0.0.1:6379> rpush list "F" "G" //["C","D","E","F","G"]
(integer) 5
相当于执行了
127.0.0.1:6379> rpush list "C" "D" "E" "F" "G"
一条命令
所以新的AOF文件只需要保存上面的一条命令即可!
服务器主程序依然用来处理客户端请求
AOF重写通过后台子进程完成