单机数据库实现——客户端
Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理服务端发送的命令请求,并向客户端返回命令回复。
客户端属性
分两种,一种通用属性,一种特定功能的相关属性,本章讲解通用属性这一部分
一,套接字描述符
根据客户端类型的不同,记录套接字描述符的fd属性的值可以是-1或者是大于-1的整数
二,名字
默认情况下,一个连接到服务器的客户端是没有名字的。但是可以使用CLIENTsetname命令设置一个名字,设置的名字将会保存在客户端状态的那么属性里面
typedef struct redisClient{
//...
robj *name;
//...
}redisClient;
同理如果客户端没有为自己设置名字,那么相应客户端状态的name属性指向NULL指针。
三,标志
客户端的标志属性flags记录了客户端的角色(role),以及客户端目前所处的状态
typedef struct redisClient{
//...
int flags;
//...
}redisClient;
其中设置了一些常量的标志来记录客户端角色的状态
四,输入缓冲区
客户端状态的输入缓冲区用于保护客户端发送的命令请求:
typedef struct redisClient{
//...
sds querybuf;
//...
}redisClient;
输入缓冲区会根据输入内容动态地缩小或者扩大,但它的最大大小不能超过1GB,否则服务器将关闭这个客户端
五,命令与命令参数
服务器将客户端发送的命令请求保存到客户端状态的querybuf属性之后,对其进行分析得出命令和命令参数分别保存到argv属性和argc属性
typedef struct redisClient{
//...
robj **argv;
int argc;
//...
}redisClient;
六,命令的实现函数
其实也就是在数据队列中找到argv[0]的值,在命令表中查找命令所对应的命令实现函数
七,输出缓冲区
执行命令所得的命令会被保存在客户端状态的输出缓冲区里面,每个客户端都有输出缓冲区可用,一个缓冲区大小是固定的,另外一个缓冲区大小是可变的。
typedef struct redisClient{
//...
char buf[REDIS_REPLY_BYTES];
int bufpos;
//...
}redisClient;
当buf固定缓冲区用完后,就会使用bufpos动态缓冲区,REDIS_REPLY_BYTES常量目前的默认值为16*1024,也就是16KB。
八,身份验证
有一个属性authenticated来记录客户端是否通过了身份验证,这里就不细说了
九,时间
分别使用几个不同的属性来记录不同状态下的时间,这里不细说了
客户端的创建与关闭
一,创建普通客户端
新创建的客户端将会添加到clients链表的末尾
二,关闭普通客户端
主要分为正常退出,强制退出,不符合协议格式的命令请求会退出
三,Lua脚本的伪客户端
struct redisClient{
//...
redisClient *lua_client;
//...
};
lua_client伪客户端在服务器运行的整个生命周期中会一直存在,只有服务器被关闭时,这个客户端才会被关闭
四,AOF文件的伪客户端
服务器在载入AOF文件时,会创建用于执行AOF文件包含的Redis命令的伪客户端,并在载入完成之后,关闭这个伪客户端。