reids设计与实现---单机数据库的实现
1服务器中的数据库
/* Redis database representation. There are multiple databases identified
* by integers from 0 (the default database) up to the max configured
* database. The database number is the 'id' field in the structure. */
typedef struct redisDb {
// 数据库键空间,保存着数据库中的所有键值对
dict *dict; /* The keyspace for this DB */
// 键的过期时间,字典的键为键,字典的值为过期事件 UNIX 时间戳
dict *expires; /* Timeout of keys with a timeout set */
// 正处于阻塞状态的键
dict *blocking_keys; /* Keys with clients waiting for data (BLPOP) */
// 可以解除阻塞的键
dict *ready_keys; /* Blocked keys that received a PUSH */
// 正在被 WATCH 命令监视的键
dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
struct evictionPoolEntry *eviction_pool; /* Eviction pool of keys */
// 数据库号码
int id; /* Database ID */
// 数据库的键的平均 TTL ,统计信息
long long avg_ttl; /* Average TTL, just for stats */
} redisDb;
```
2 数据库的键空间
数据库的键空间是一个字典
3 键的过期处理
1 键的过期时间
虽然有多种不同单位和不同形式的设置命令,但实际上EXPIRE、PEXPIRE、EXPIREAT三个命令都是使PEXPIREAT命令来实现的:无论客户端执行的是以上四个命令中的哪一个,经过转换之后,最终的执行效果都和执PEXPIREAT命令一样
2 过期键删除策略
3 AOF、RDB、和复制功能对过期键的处理
P111
4 RDB的持久化
# RDB持久化
Redis提供了RDB持久化功能,这个功能可以将Redis在内存中的数据库状态保存到磁盘里面,避免数据意外丢失
RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态
## RDB文件的创建与载入
SAVE命令为阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求
BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求
5 AOF持久化
# AOF持久化
与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。
## 命令追加
当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式化将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾
AOF文件的载入与数据还原
AOF重写
## AOF重写
为了解决AOF文件体积膨胀的问题,Redis提供了AOF文件重写(rewrite)功能。通过该功能,Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库状态相同,但新AOF文件不会包含任何浪费空间的冗余命令,所以AOF文件的体积通常会比旧AOF文件的体积小得多
这个功能是通过读取服务器当前的数据库状态来实现的在子进程中进行
为了解决这种数据不一致问题,Redis服务器设置了一个AOF重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当Redis服务器执行完一个写命令之后,它会同时将这个写命令发送给AOF缓冲区和AOF重写缓冲区
在整个AOF重写过程中,只有信号处理函数执行时会对服务器进程(父进程)造成阻塞。
6 事件
# 事件
文件事件:Redis服务器通过套接字与客户端(或者其他Redis服务器)进行连接,而文件事件就是服务器对套接字操作的抽象
时间事件:Redis服务器中的一些操作(比如serverCron函数)需要在给定的时间点执行,而时间事件就是服务器对这类定时操作的抽象
文件事件
事件的调度与执行
7 客户端
套接字
名字
标志
输入缓冲区
输出缓冲区
身份验证
时间
客户端的创建 1创建普通客户端 2Lua脚本的伪客户端 3AOF文件的伪客户端
8 服务端
## 命令请求的执行过程
1. 当用户在客户端中键入一个命令请求时,客户端会将这个命令请求转换成协议格式,然后通过连接到服务器的套接字,将协议格式的命令请求发送给服务器
2. 当客户端与服务器之间的连接套接字因为客户端的写入而变得可读时,服务器将调用命令请求处理器来执行以下操作(输入缓冲区、argv、argc)
3. 命令执行器要做的第一件事就是根据客户端状态的argv[0]参数,在命令表中查找参数所指定的命令,并将找到的命令保存到客户端状态的cmd属性里面
4. 执行预备
5. 调用命令的实现函数
6. 执行后续工作
7. 将命令回复发送给客户端,客户端接收并打印命令回复
命令请求的执行过程
1 命令执行器 查找命令实现
2 命令执行器 执行预备操作
3 命令执行器 调用命令的实现函数
4 命令执行器 执行后续工作
5 将命令回复发送给客户端
6 客户端接收并打印命令回复
serverCron函数
1 更新服务器时间缓存
2 更新LRU时钟
3 更新服务器每秒执行命令次数
4 更新服务器内存峰值记录
5 处理SIGTERM
6 管理客户端资源
7 管理数据库资源
8 执行被延迟的BGREWRITEAOF
9 检查持久化操作的运行状态
10将AOF缓冲区中的内容写入AOF文件
11 关闭异步客户端
12 增加cronloops计数器的值
初始化服务器
1 初始化服务器状态结构
2 载入装置选项
3 初始化服务器数据结构
4 还原数据库状态
5 执行事件循环