目录
1、客户端
redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立起网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复。
redis服务器状态结构的clients属性是一个链表,这个链表保存了所有与服务器连接的客户端状态结构,对客户端执行批量操作或者查找某个指定的客户端,都可以通过遍历clients链表完成:
1.1客户端属性
1.1.1套接字描述符
客户端状态的fd属性记录了客户端正在使用的套接字描述符:
typedef struct redisClient {
//...
int fd;
//...
}redisClient
1.1.2名字
在默认情况下,一个连接到服务器的客户端是没有名字的。
使用CLIENT setname 命令可以为客户端设置一个名字,让客户党的身份变得更加清晰。
客户端的名字记录在客户端状态的name属性里面:
typedef struct redisClient {
//...
robj *name;
//...
}redisClient
如果客户端没有为自己设置名字,那么相应客户端状态的name属性指向NULL指针;相反的,就会指向一个字符串对象。
1.1.3标志
客户端的标志属性flags记录了客户端的角色,以及客户端目前所处的状态
typedef struct redisClient {
//...
int flags;
//...
}redisClient
每个标志使用一个常量表示,一部分标志记录了客户端的角色:
而另一部分标志则记录了客户端目前所处的状态:
1.1.4输入缓冲区
客户端状态的输入缓冲区用于保存客户端发送的命令请求:
typedef struct redisClient {
//...
sds querybuf;
//...
}redisClient
1.1.5命令与命令参数
1.1.6命令的实现函数
针对命令表的朝族不区分输入字母的大小写
1.1.7输出缓冲区
执行命令所得的命令回复会被保存在客户端状态的输出缓冲区里面,每个客户端都有两个输出缓冲区可用,一个缓冲区的大小是固定的,另一个缓冲区的大小是可变的。
1.1.8身份验证
客户端状态的authenticated 属性用于记录客户端是否通过了身份验证:如果这个属性的值为0那么代表客户端未通过身份验证,如果为1则表示已经通过了身份验证。
typedef struct redisClient {
//...
int authenticated;
//...
}redisClient
1.1.9时间
1.2客户端的创建与关闭
服务器使用不同的方式来创建和关闭不同类型的客户端,本节将介绍服务器创建和关闭客户端的方法。
1.2.1创建普通客户端
1.2.2关闭普通客户端
一个客户端可以因为多种原因而被关闭:
1.2.3Lua脚本的伪客户端
1.2.4AOF文件的伪客户端
2、服务器
2.1命令请求的执行过程
1.1.1发送命令请求
2.1.2读取请求命令
2.1.3命令执行器(1):查找命令实现
2.1.4命令执行器(2):执行预备操作
在真正执行命令之前,程序还需要进行一些预备操作,从而确保命令可以正确、顺利地被执行,这些操作包括:
2.1.5命令执行器(3):调运命令的实现函数
2.1.6命令执行器(4):执行后续工作
2.1.7将命令回复发送给客户端
命令实现函数会将回复保存到客户端的输出缓冲区里面,并为客户端的套接字关联命令回复处理器,当客户端套接字变为可写状态时,服务器就会执行命令回复处理器,将保存在客户端输出缓冲区中的命令回复发送给客户端。当命令回复发送完毕之后,回复处理器会清空客户端状态的输出缓冲区的,为处理下一个命令请求做好准备。
2.1.8客户端接收并打印命令回复
2.2severCron函数
redis服务器中有不少功能需要获取系统的当前时间,而每次获取系统的当前时间都需要执行一次系统调用,为了减少系统调用的执行次数,服务器状态中的unixtime属性和mstime属性被用作当前时间的缓存:
struct redisServe{
//...
//保存了秒级进度的系统当前UNIX时间戳
time_t unixtime
//保存了毫秒级进度的系统当前UNIX时间戳
long long mstime;
//...
};
因为serveCron函数默认会以每100毫秒一次的频率更新unixtime属性和mstime属性,所以这两个属性记录的时间的精确度并不高:
2.2.2更新LRU时钟
当服务器要计算一个数据库的空转时间(也即是数据空键对应的值对象的空转时间),程序会用服务器的lruclock属性记录的时间减去对象的lru属性记录的时间,得出的计算结果就是这个对象的空转时间:
2.2.3更新服务器每秒执行命令的次数
2.2.4更新服务器内存峰值记录
2.2.5处理SIGTERM信号
2.2.6管理客户端资源
2.2.7管理数据库资源
2.2.8执行被延迟的BGREWRITEAOF
2.2.9检查持久化操作的运行状态
2.2.10将AOF缓冲区中的内容写入AOF文件
2.2.11关闭异步客户端
在这一步,服务器会关闭那些输出缓冲区大小超出限制的客户端。
2.2.12增加cronloops计数器的值
2.3初始化服务器
2.3.1初始化服务器状态结构
初始化服务器的第一步就是创建一个struct redisServe类型的实例变量server作为服务器的状态,并为结构中各个属性设置默认值。
2.3.2载入配置选项
2.3.3初始化服务器数据结构
2.3.4还原数据库状态
在完成了对服务器状态server变量的初始化之后,服务器需要载入RDB文件或者AOF文件,并根据文件记录的内容来还原服务器的数据库状态。
2.3.5执行时间循环