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链表

相关推荐
NineData2 分钟前
NineData智能数据管理平台新功能发布|2026年1-2月
数据库·sql·数据分析
IvorySQL1 小时前
双星闪耀温哥华:IvorySQL 社区两项议题入选 PGConf.dev 2026
数据库·postgresql·开源
狼爷1 小时前
Go 没有 override?别硬套继承!用接口+嵌入,写更清爽的“覆盖”逻辑
java·go
小兔崽子去哪了4 小时前
Java 自动化部署
java·后端
ma_king4 小时前
入门 java 和 数据库
java·数据库·后端
后端AI实验室4 小时前
我用Cursor开发了3个月,整理出这套提效4倍的工作流
java·ai
jiayou647 小时前
KingbaseES 实战:审计追踪配置与运维实践
数据库
码路飞8 小时前
GPT-5.3 Instant 终于学会好好说话了,顺手对比了下同天发布的 Gemini 3.1 Flash-Lite
java·javascript
SimonKing9 小时前
OpenCode AI编程助手如何添加Skills,优化项目!
java·后端·程序员
Seven9710 小时前
剑指offer-80、⼆叉树中和为某⼀值的路径(二)
java