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

相关推荐
二哈赛车手6 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
栗子~~7 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
YDS8297 小时前
DeepSeek RAG&MCP + Agent智能体项目 —— RAG知识库的搭建和接口实现
java·ai·springboot·agent·rag·deepseek
隔窗听雨眠7 小时前
多活部署、CDN加速与边缘缓存全链路优化实战
缓存
星星也在雾里8 小时前
PgBouncer 解决 PostgreSQL 连接数超限 + 可视化监控
数据库·postgresql
未若君雅裁8 小时前
MyBatis 一级缓存、二级缓存与清理机制
java·缓存·mybatis
AI人工智能+电脑小能手9 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
阿维的博客日记9 小时前
Nacos 为什么能让配置动态生效?(涉及 @RefreshScope 注解)
java·spring
雨辰AI9 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
长城202410 小时前
关于MySql的ONLY_FULL_GROUP_BY问题
数据库·mysql·聚合列