概念
Redis服务器是一个典型的一对多程序,对于每个与服务器进行连接的客户端,服务器都在内部保存了对应的状态信息,以及执行相关的操作需要用到的数据结构:
struct redisServer {
// ...
list *clients;
// ...
}
clients属性是一个链表,记录着所有的客户端信息。
一些重要的属性
struct redisClient {
int fd; // 套接字描述符
robj *name; // 名字
int flags; // 标志
sds querybuf; // 输入缓冲区
robj *argv; // 命令及参数
int argc; // argv数组的长度
struct redisCommand *cmd; // 命令的实现函数
char buf[REDIS_REPLY_BYTES]; // 字节数组(字节缓冲区)
int bufpos; // 字节数组中已使用的字节数
int authenticated; // 是否通过了身份验证
list *reply; // 缓冲区链表
time_t ctime; // 客户端的创建时间
time_t lastinteraction; // 客户端与服务器最后一次互动的时间
time_t obuf_soft_limit_reached_time; // 输出缓冲区第一次触达软性限制的时间
}
fd属性
该属性是整数类型,要么是-1,要么大于-1。因为文件描述符都是大于等于0的整数,如果值为-1的话,就证明这是一个伪客户端。
name属性
通常情况下,客户端是没有名字的,即name属性指向null,可通过对应的命令进行设置。设置好名字后,name属性就指向一个字符串对象。
flags属性
该属性记录了客户端的角色以及当前所处的状态。属性值可以是单个标志,也可以是多个。这里找了篇文章,感兴趣的可自行阅读:https://blog.csdn.net/qq_34901859/article/details/138483662
querybuf属性
用于保存客户端发送的命令请求。输入缓冲区会根据内容动态的调整大小,但有个上限,1GB,超出之后服务器将会关闭该客户端。
argv属性
服务器将客户端的请求保存到对应的输入缓冲区后,会进行内容的解析,解析后的结果放入 argv 数组中,argv[0]表示命令,剩下的数组元素表示命令后面的参数。
cmd属性
根据argv[0]的值,在命令表(dict)中进行查找,对应的命令实现函数,然后执行。
输出缓冲区
有两个实现,一个数规定大小的数组(buf[REDIS_REPLY_BYTES]),一个是串连字符串对象的链表(reply)。
数组的长度规定为 16 * 1024 字节,即16kb,适合保存那些内容较短的回复。
身份验证
authenticated的值为0,表示客户端未通过身份验证;值为1表示已通过身份验证。
输出缓冲区的限制策略
硬性限制:输出缓冲区的大小超出硬性限制的大小后,关闭客户端。
软性限制:如果输出缓冲区的大小触达了软性限制大小,服务器会将 obuf_soft_limit_reached_time 属性设置一个起始时间。如果限制时间到达了,输出缓冲区没有超出软性限制,那么 obuf_soft_limit_reached_time 置为0,取消监视。否则,若还是超出,则关闭客户端。
Lua脚本的伪客户端
服务器初始化时,会创建一个负责执行lua脚本中包含Redis命令的伪客户端:
struct redisServer {
// ...
redisClient *lua_client;
// ...
}
这个客户端和服务器的生命周期一致。
AOF文件的伪客户端
服务器在载入AOF文件文件时,也会创建一个用于执行AOF文件中的命令的客户端,文件载入完毕时关闭。
2024.10.28
writeBy kaiven