目录
1.Client简介
2.客户端属性
1)(本文重点)比较通用的属性
2)(后续分享)另外一类是和特定功能相关的属性
2.1套接字文件描述符
2.2名字
2.3标志(flag)
2.4输入缓冲区
2.5命令参数和个数
2.6命令函数
2.7输出缓冲区
3.总结
1.Client简介
Redis 服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,
每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并
向客户端返回命令回复。
通过使用由1/0多路复用技术实现的文件事件处理器,Redis 服务器使用单线程单进程
的方式来处理命令请求,并与多个客户端进行网络通信。
对于每个与服务器进行连接的客户端,服务器都为这些客户端建立了相应的redis.h/
redisclient 结构(客户端状态),这个结构保存了客户端当前的状态信息,以及执行相
关功能时需要用到的数据结构,其中包括:
Redis 服务器状态结构的 clients属性是一个链表,这个链表保存了所有与服务器连
接的客户端的状态结构,对客户端执行批量操作,或者查找某个指定的客户端,都可以通过遍历clients连表完成。
2.客户端属性
客户端状态包含的属性可以分为两类:
1)(本文重点)比较通用的属性
这些属性很少与特定功能相关,无论客户端执行的是什么
工作,它们都要用到这些属性。
2)(后续分享)另外一类是和特定功能相关的属性
比如操作数据库时需要用到的ab 属性和dictid属性,执行事务时需要用到的mstate 属性,以及执行 WATCH命令时需要用到的watched_keys 属性等等。
本章将对客户端状态中比较通用的那部分属性进行介绍,至于那些和特定功能相关的属
性,后面会继续分享。
2.1套接字文件描述符
客户端状态的fd属性记录了套接字描述符。
tydedef struct redisClient{
int fd;
}
根据客户端类型的不同,fd属性的值可以是-1或者是大于-1 的整数:
1)伪客户端(fake client)的fd属性的值为-1:伪客户端处理的命令请求来源于AOF
文件或者Lua脚本,而不是网络,所以这种客户端不需要套接字连接,自然也不需
要记录套接字描述符。目前 Redis 服务器会在两个地方用到伪客户端,一个用于载
人AOF 文件并还原数据库状态,而另一个则用于执行Lua 脚本中包含的Redis命令。
2) 普通客户端的Ed属性的值为大于-1的整数:普通客户端使用套接字来与服务器进
行通信,所以服务器会用fd 属性来记录客户端套接字的描述符。因为合法的套接字
描述符不能是-1,所以普通客户端的套接字描述符的值必然是大于-1 的整数。
2.2名字
在默认情况下,一个连接到服务器的客户端是没有名字的。
比如在下面展示的 CLIENT list命令示例中,两个客户端的name 域都是空白的:
设置名字:setname命令
2.3标志(flag)
用了记录client的角色,以及处于什么状态。
tydedef struct redisClient{
int flags;
}
每个标志使用一个常量表示,一部分标志记录了客户端的角色:
1)在主从服务器进行复制操作时,主服务器会成为从服务器的客户端,而从服务器也
会成为主服务器的客户端。REDIS_MASTER 标志表示客户端代表的是一个主服务
器,REDIS_SLAVE 标志表示客户端代表的是一个从服务器。
REDIS_PRE_PSYNC标志表示客户端代表的是一个版本低于 Redis2.8的从服务器,
主服务器不能使用PSYNC命令与这个从服务器进行同步。这个标志只能在 REDIS_
SLAVE 标志处于打开状态时使用。
2)REDIS_LUA_CLIENT标识表示客户端是专门用于处理Lua 脚本里面包含的 Redis
命令的伪客户端。
而另外一部分标志则记录了客户端目前所处的状态:
3) REDIS_MONITOR标志表示客户端正在执行MONITOR命令。
4)REDIS_UNIX_SOCKET 标志表示服务器使用 UNIX 套接字来连接客户端。
5) REDIS_BLOCKED 标志表示客户端正在被 BRPOP、BLPOP等命令阻塞。
6) REDISUNBLOCKED 标志表示客户端已经从 REDIS_BLOCKED 标志所表示的阻塞状
2.4输入缓冲区
用于保存客户端发送的命令请求
最大限制:1G
tydedef struct redisClient{
sds querybuf;
}
2.5命令参数和个数
在服务器将客户端发送的命令请求保存到客户端状态的querybuf 属性之后,服务器
将对命令请求的内容进行分析,并将得出的命令参数以及命令参数的个数分别保存到客户端
状态的 argv 属性和 argc属性:
argv 属性是一个数组,数组中的每个项都是一个字符串对象,其中 argv[0]是要执
行的命令,而之后的其他项则是传给命令的参数。
argc属性则负责记录 argv 数组的长度。
2.6命令函数
当服务器从协议内容中分析并得出 argv 属性和 arge 属性的值之后,服务器将根据项
argv 101的值,在命令表中查找命令所对应的命令实现函数。
图13-7展示了一个命令表示例,该表是一个字典,字典的键是一个 SDS结构,保存
了命令的名字,字典的值是命令所对应的rediscommand 结构,这个结构保存了命令的实
现函数、命令的标志、命令应该给定的参数个数、命令的总执行次数和总消耗时长等统计
信息。
2.7输出缓冲区
服务端执行命令的回复,会保存到输出缓冲区,共2个缓冲区
1)固定大小:存OK,错误命令,简单的字符串,整数值
2)可变的:长字符串,列表,集合等。
通过使用链表来连接多个字符串对象,服务器可以为客户端保存一个非常长的命令回 复,而不必受到固定大小缓冲区16KB大小的限制。
3.总结
口客户端状态的Elags 属性使用不同标志来表示客户端的角色,以及客户端当前所处
的状态。
口 输人缓冲区记录了客户端发送的命令请求,这个缓冲区的大小不能超过1GB。
口 命令的参数和参数个数会被记录在客户端状态的 argv 和 argc 属性里面,而 cmd
属性则记录了客户端要执行命令的实现函数。
口 客户端有固定大小缓冲区和可变大小缓冲区两种缓冲区可用,其中固定大小缓冲区
的最大大小为16 KB,而可变大小缓冲区的最大大小不能超过服务器设置的硬性限
制值。
口 输出缓冲区限制值有两种,如果输出缓冲区的大小超过了服务器设置的硬性限制,
那么客户端会被立即关闭;除此之外,如果客户端在一定时间内,一直超过服务器
设置的软性限制,那么客户端也会被关闭。
口 当一个客户端通过网络连接连上服务器时,服务器会为这个客户端创建相应的客户
端状态。网络连接关闭、发送了不合协议格式的命令请求、成为 CLIENT KILL 命令
的目标、空转时间超时、输出缓冲区的大小超出限制,以上这些原因都会造成客户
端被关闭。
口处理Lua 脚本的伪客户端在服务器初始化时创建,这个客户端会一直存在,直到服
务器关闭。
口 载人AOF 文件时使用的伪客户端在载人工作开始时动态创建,载人工作完毕之后关闭。