Redis12:客户端

客户端

对于每个与服务器进行连接的客户端,服务器都为这些客户端建立了相应的redisClient结构,这个结构代表客户端状态,redis服务器状态结构的clients属性记录了所有与服务器连接的客户端的状态结构,它是一个链表,如一个服务器与三个客户端连接:

客户端状态包含的属性可以分为两类:一类是比较通用的属性,和特定功能基本不相关,一类是和特定功能相关的属性。这里主要介绍第一类属性。

客户端属性

套接字描述符

在redisClient中,int类型的fd代表对应客户端的套接字描述符。

如果fd是-1,代表该客户端为伪客户端,伪客户端处理的命令请求来源于AOF文件或Lua脚本,而不是网络。

如果fd是大于-1的整数,就代表该客户端为普通客户端。

执行下列命令可以列出所有连接到服务器的普通客户端:

client list

命令执行后会显示很多结果,包括每个服务器的fd(套接字描述符)、name(客户端名)、age(已经连接的秒数)、idle(空转秒数:距离客户端与服务器最后一次进行互动以来过去的秒数)

客户端名字

默认一个连接到服务器的客户端是没有名字的,需要执行下列命令来为客户端设置一个名字:

client setname 名

名字可以根据客户端的作用来自定义。

标志

标志属性是int类型的,名字为flags,它的值通常都是一个常量,标志属性记录了客户端的角色和客户端所处的状态,以下是一些flags属性的例子:

REDIS_MASTER代表客户端是一个主服务器。

REDIS_BLOCKED代表客户端正在被列表命令阻塞。

REDIS_MULTI | REDIS_DIRTY_CAS代表客户端正在执行事务,但事务的安全性已被破坏。

(这个值有时会用或来代表同时处于多个状态)

输入缓冲区

客户端的输入缓冲区是用来保存客户端发送的命令的,它的类型是sds,名字为querybuf。当客户端向服务器发送命令请求时,服务器的客户端状态的querybuf就会记录该命令的协议值,它最大不能超过1G,否则服务器就会关闭这个客户端。

命令和命令参数

服务器将命令请求保存在客户端状态的querybuf属性后,就会对命令内容进行分析,将分析得出的命令参数及命令参数个数保存在客户端的argv属性和argc属性,argv是一个数组类型,它的每一项都是一个字符串对象,其中第一项是要执行的命令,后面是命令的参数,而argc负责记录argv数组的长度。

如客户端发送的命令是set key value,那么argv和argc属性就分别是:

命令的实现函数

在得到上述属性后,服务器会根据argv[0]的值,在命令表中查找命令所对应的命令实现函数。

命令表是一个字典,输入一个SDS命令名称,就能找到一个redisCommand结构,客户端的cmd指针就会指向这个结构。至此,服务器的客户端状态已经拥有了命令参数信息、命令参数、执行命令对应的实现函数。

输出缓冲区

输出缓冲区用来装入服务器发回来的命令执行结果的。每个客户端都有两个输出缓冲区可用,一个是固定大小的缓冲区,一个是可变大小的缓冲区。

固定大小的缓冲区由一个名为REDIS_REPLY_CHUNK_BYTES的char数组和一个名为bufpos的int数组成,前者是一个大小为16KB的缓冲区,后者记录了该缓冲区中目前使用的字节数量。

当数组空间已经用完或者结果太大无法放入其中时,服务器就会开始使用可变大小缓冲区,可变大小缓冲区由一个reply链表组成,这个链表连接了多个字符串对象,可以保存非常长的结果。

身份验证

客户端状态有一个名为authenticated的int数,它用于记录客户端是否通过了验证。

如果该值是0,代表未通过验证,是1代表通过验证。如果未通过验证的客户端向服务器发送命令,那么除了auth外的所有命令服务器都会拒绝执行,只有客户端向服务器发送auth命令成功进行身份验证后,该值从0变成1,才能恢复正常。

默认只有在服务器启用了身份验证功能时才能使用,如果未启用该功能那么该值默认是0.

时间

客户端状态有几个和时间相关的属性:

ctime记录了创建客户端的时间、lastinteraction记录了客户端与服务器最后一次互动的时间、obuf_soft_limit_reached_time记录了输出缓冲区第一次达到软性限制soft limit的时间。

通过这三个时间,可以计算出客户端的存活时间age和空转时间idle。

客户端的创建和关闭

普通客户端的创建和关闭

客户端使用connect函数连接到服务器时,服务器就会调用连接事件处理器,为客户端建立相应的客户端状态,并将这个新的客户端状态添加到服务器状态结构clients链表的末尾。

普通客户端关闭的原因有多种:

1、客户端进程退出或被杀死

2、客户端向服务器发送了不符合协议格式的命令请求

3、对某个客户端执行client kill

4、如果用户为服务器设置了timeout配置选项,当客户端的空转时间超过timeout选项设置的值时,客户端将被关闭

5、客户端发送的命令请求超过了输入缓冲区的限制大小(默认为1GB),或命令回复超出了输出缓冲区的限制大小,客户端将被关闭

客户端的可变大小输出缓冲区理论上可以保存任意长的命令回复,为了避免回复过大,占用太多的服务器资源,服务器会时刻检查输出缓冲区的大小,相关的模式有两种:

1、硬性模式hard limit:如果输出缓冲区的大小超过了硬性模式规定的大小,那么服务器立即关闭客户端

2、软性模式soft limit:如果输出缓冲区的大小超过了软性模式规定的大小,但还没超过硬性模式限制,那么服务器将记录下obuf_soft_limit_reached_time,也就是达到软性限制的起始时间,然后继续监视客户端,如果在规定时间内不再超出软性限制那么客户端就不会被关闭,如果一直超出软性限制那么客户端就会被关闭。

在配置文件中可以设置硬性模式和软性模式的参数,以及针对的客户端类型:

不限制普通客户端的输出缓冲区:
client-output-buffer-limit normal 0 0 0
限制从服务器客户端:
client-output-buffer-limit slave 256mb 64mb 60
限制执行发布与订阅功能的客户端:
client-output-buffer-limit pubsub 32mb 8mb 60

其他客户端的创建和关闭

对于Lua脚本的伪客户端,服务器会在初始化时创建负责执行Lua脚本中包含的redis命令的伪客户端,关联在redisServer中的名为lua_client的redisClient类型中。它在服务器运行的整个生命周期都存在,直到服务器被关闭它才会被关闭。

服务器在载入AOF文件时,会创建对应的伪客户端,载入完成后关闭这个客户端。

posted @ 2019-09-15 19:01  勇闯8  阅读(374)  评论(0编辑  收藏  举报