Redis中的客户端(二)

客户端

输入缓冲区。

客户端状态的输入缓冲区用于保存客户端发送的命令请求:

c 复制代码
typedef struct redisClient {
 // ...
 sds querybuf;
 
 // ...
}redisClient;

例子

举个例子,如果客户端向服务器发送了以下命令请求:

c 复制代码
SET key value

那么客户端状态的qureybuf属性将是一个包含以下内容的SDS值

c 复制代码
*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n

如图所示占了这个SDS值以及querybuf属性的样子。输入缓冲区的大小会

根据输入内容动态地缩小或者扩大,但它的最大大小不能超过1GB,否则服务器将关闭这个客户端

命令与命令参数

在服务器将客户端发送的命令请求保存到客户端状态的querybuf属性之后,服务器将对命令请求的内容进行分析,并将得出的命令参数以及命令参数的个数分别保存到客户端状态的argv属性和argc属性:

c 复制代码
typedef struct redisClient {
 // ...
 robj **argv;
 
 int argc;
 // ...
}redisClient

argv属性是一个数组,数组中的每个项都是一个字符串对象,其中argv[0]是要执行的命令,而之后的其他项则是传给命令的参数。

argc属性则是负责记录argv数组的长度。

例子

  • 举个例子,图中展示的客户端状态中,argc属性的值伪3,而不是2,
    因为命令的名字"SET"本身也是一个参数

命令的实现函数

当服务器从协议内容中分析并得出argv属性和argc属性的值之后,服务器将根据项argv[0]的值,在命令表中查找命令所对应的命令实现函数。

图中展示了一个命令表示例,该表是一个字典,字典的键是一个SDS结构,保存了命令的名字,字典的值是命令所对应的rediCommand结构,这个结构保存了命令的实现函数、命令的标志、命令应该给定的参数个数、命令的总执行次数和总消耗时长等统计信息。当程序在命令表中成功找到argv[0]所对应的redisCommand结构时,它会将客户端状态的cmd

指针指向这个结构:

c 复制代码
typedef struct redisClient {
 // ...
 struct redisCommand *cmd;
 // ...
}redisClient

之后,服务器就可以使用cmd属性所指向的redisCommand结构,以及argv、argc属性中保存的命令参数信息,调用命令实现函数,执行客户端指定的命令

图中演示了服务器在argv[0]为"SET"时,查找命令表并将客户端状态的

cmd指针指向目标redisCommand结构的整个过程。针对命令表的查找操作不区分输入字母的大小写,所以无论argv[0]是"SET"、"set" 、或者"Set"等等,查找的结构都是相同的。

输出缓冲区

z执行命令所得的命令回复会被保存在客户端状态的输出缓冲区里面,每个客户端都有两个输出缓冲区可用,一个缓冲区的大小是固定的,另一个缓冲区的大小是可变的:

  • 1.固定大小的缓冲区用于保存那些长度比较小的回复,比如OK、间段的字符串值、整数值、错误回复等等
  • 2.可变大小的缓冲区用于保存那些长度比较大的回复,比如一个非常长的字符串值,一个由很多项组成的列表,一个包含了很多元素的集合等等。客户端的固定大小缓冲区由buf和bufpos两个属性组成:
c 复制代码
typedef struct redisClient {
 // ...
 char buf[REDIS_REPLY_CHUNK_BYTS];
 
 int bufpos;
 // ...
}redisClient;

buf是一个大小为REDIS_REPLY_CHUNK_BYTES字节的字节数组,而bufpos属性则记录了buf数组目前已使用的字节数量。REDIS_REPLY_CHUNK_BYTES常量目前的默认值为16*1024,也就是说,buf数组的默认大小为16KB.如图展示了一个使用固定大小缓冲区来保存返回值+OK\r\n的例子。当buf数组的空间已经用完,或者回复因为太大而没办法放进buf数组里面时,服务器就会开始使用可变

大小缓冲区。可变大小缓冲区由reply链表和一个或多个字符串对象组成:

c 复制代码
typedef struct redisClient {
 // ...
 list *reply;
 // ...
}redisClient

通过使用链表l来连接多个字符串对象,服务器可以为客户端保存一个非常长的命令回复,而不必受到固定

大小缓冲区16KB大小的限制。

例子

如图展示了一个包含三个字符串对象的reply链表

相关推荐
月空MoonSky9 分钟前
Oracle中TRUNC()函数详解
数据库·sql·oracle
momo小菜pa9 分钟前
【MySQL 06】表的增删查改
数据库·mysql
杨哥带你写代码16 分钟前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
小字节,大梦想17 分钟前
【C++】二叉搜索树
数据结构·c++
我是哈哈hh38 分钟前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
郭二哈42 分钟前
C++——模板进阶、继承
java·服务器·c++
A尘埃1 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23071 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
沉登c1 小时前
幂等性接口实现
java·rpc
代码之光_19801 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端