Redis设计与实现读书笔记---数据库/RDB/AOF

数据库

数据库与客户端

Redis服务器的所有数据库都保存在redisServer结构的db数组中,根据dbnum属性初始化数据库的数量;

struct redisServer{
    //.....
    //一个数组,保存服务器中的所有数据库
    redisDb *db;
    //服务器的数据库数量,默认16个
    int dbnum;
}

切换数据库:select 1;

服务器的内部,客户端状态redisClient结构记录客户端的状态

typedef struct redisclient{
    //记录客户端当前使用的数据库
    redisDb *db;
}redisClient

数据库键空间

Redis是一个键值对(key-value pair)数据库服务器,服务器中的每个数据库信息由redisDb保存,其中有个属性dict字典保存所有的键值对,这个字典就是键空间。

typedef struct redisDb{
    //数据库键空间,保存着数据库中所有键值对
    dict *dict;
}

设置过期时间

EXPIRE KEY TTL:将键key的生存时间设置为ttl秒

PEXPIRE KEY TTL:将键key的生存时间设置为ttl毫秒

EXPIRE KEY TIMESTAMP:将键key的过期时间设置为timestamp所指定的秒数时间戳

PEXPIRE KEY TIMESTAMP:将键key的过期时间设置为timestamp所指定的毫秒数时间戳

PERSIST key:移除过期时间。

TTL:计算键的过期时间与当前时间之差,以秒为单位返回。

PTTL:计算键的过期时间与当前时间之差,以豪秒为单位返回。

redisDb结构的属性expires字典保存数据库中所有键的过期时间,这个字典称为过期字典。

typedef struct redisDb{
	//过期字典,保存着键的过期时间
    dict *expires;
}

过期键删除策略

键的过期删除策略有三种:

  1. 定时删除:主动删除,在设置键的过期时间的同时,创建一个定时器,让定时器在键过期时间来临的时候,立即对键进行删除操作;(内存友好)
  2. 惰性删除:被动删除,放任键过期不管,每次从键空间获取键的时候,都检查键是否过期,过期则删除。(CPU友好)
  3. 定期删除:主动删除,每隔一段时间,程序对数据库进行检查,删除里面的过期键。(折中处理方案)

在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会保存到新创建的RDB文件中;

主服务器在载入RDB文件的时候,会对过期键进行筛选,不将过期的键录入,而从服务器在载入RDB文件的时候,会将过期的键也录入;

当服务器以AOF模式运行时,不会收到过期键的影响,当过期键被惰性删除或定期删除后,AOF文件会追加一条DEL命令来显式地删除该键。

AOF重写的时候,不会将过期的键写入文件。

复制模式下,从服务器不会主动去删除过期的键,都是由主服务器去控制,当主服务器向从服务器发送删除命令的时候,从服务器才回去删除过期的键。

RDB持久化

数据库状态:服务器中的非空数据库及其键值对
RDB文件:一个压缩的二进制文件,用来记录数据库状态

生成RDB文件

SAVE:阻塞Redis服务器进程,直到RDB文件创建完毕为止。

BGSAVE:命令会派生出子进程,由子进程去完成RDB文件创建,父进程继续响应命令处理。

AOF文件的更新频率会比RDB文件的更新频率高,所以如果服务器启动了AOF持久化功能,服务器会优先使用AOF文件还原数据库状态

自动间隔性保存

服务器默认的保存策略

SAVE 900 1:服务器在900秒内,对数据库进行了至少一次修改;

SAVE 300 10:服务器在300秒内,对数据库进行了至少10次修改;

SAVE 60 10000:服务器在60秒内,对数据库进行了至少10000次修改;

保存条件的数据结构

struct redisServer{
	//记录保存条件的数组
    struct saveparam *saveparams;
}
struct saveparam{
    //秒数
    time_t seconds;
    //修改数
    int changes;
}

RDB文件结构

redis | db_version | databases | eof | check_sum

redis:文件头,保存REDIS字符用于标识文件;

db_version:长度4字节 ,记录RDB文件版本号;

databases:包含零个或任意多个数据库,以及各数据库中的键值对数据;

​ 保存的数据结构为:SELECTDB | db_number | key_value_pairs

eof:常量的长度为1字节,标识RDB文件正文结束;

check_sum:8字节长的无符号整数,保存校验和。

打印RDB文件:od -c dump.rdb

AOF持久化

AOF持久化时通过保存Redis服务器执行的写命令来记录数据状态,被写入AOF文件的所有命令都是以Redis命令请求协议。AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步。

命令追加

当AOF持久化功能开启,服务器在执行一个命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。

struct redisServer{
	//AOF缓冲区
    sds aof_buf;
}

文件写入与文件同步

Redis服务器进程实质上是一个事件循环,循环中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,时间事件则负责定时运行函数。

服务器在处理文件事件时都可能会执行写命令,使得一些内容被追加到aof_buf缓冲区,每次服务器结束一个事件循环前,都会调用flushAppendOnlyFile函数,决定是否将缓冲区中的内容写入到文件。

appendfsync选项的值 flushAppendOnlyFile函数
always 将aof_buf缓冲区中的所有内容写入并同步到AOF文件
everysec 每隔一秒将缓冲区的内容写入AOF文件
no 不将将aof_buf缓冲区的内容写入AOF文件

AOF文件载入和数据还原的时候,现在本地创建一个伪客户端,读取AOF文件中的命令,将命令用伪客户端执行,还原数据库状态。

AOF文件重写

AOF文件重写并不需要对已有的AOF进行读取,而是通过读取服务器当前的数据状态来实现。

AOF文件重写的时候,服务器会开辟一个新的重写缓冲区空间,当命令进入时,会将命令记录在AOF缓冲区和AOF重写缓冲区,当且仅当AOF的新文件生成后,向父进程发送信号,然后再将AOF重写缓冲区的内容录入AOF文件,原子性地将新的AOF文件替换旧的AOF文件。

上一篇:redis 两种持久化方式详解(RDB,AOF)


下一篇:深度剖析Redis6的持久化机制(大量图片说明,简洁易懂)