《Redis设计与实现》学习笔记-客户端

本文深入探讨Redis客户端状态及功能实现,详细介绍了客户端状态管理、命令执行流程、身份验证机制、时间跟踪以及输出缓冲区限制等内容。通过理解这些机制,开发者能更高效地利用Redis的特性。

Redis通过一个redisClient结构体来保存客户端当前的状态信息和执行相关功能时需要用到的数据结构,包括:

  • 套接字描述符
  • 名字
  • flags属性
  • 输入缓冲区
  • 输出缓冲区
  • 当前要执行的命令与命令参数
  • 身份验证标识
  • 时间

套接字描述符

 fd属性保存客户端正在使用的套接字描述符。如果客户端是伪客户端该属性值为-1,如果是普通客户端它是一个大于-1的整数。redis在加载AOF文件或执行Lua脚本时会创建一个伪客户端(Fake Client)。

名字

默认情况下客户端是没有名字的,当客户端执行了CLIENT setname命令之后,服务器会给该客户端设置名字,并把名字保存在redisClient结构体的name属性中。

标志

flags属性,记录了客户端的角色,以及客户端所处的状态,flags可以表示单个标志,也可以表示多个标志比如flags= flag1 | flag2 | ...。该属性有下列枚举值:

  • REDIS_MASTER,主从服务器进行复制操作时,主服务器会成为从服务器的客户端,从服务器也会成为主服务器的客户端,该状态表示客户端代表的是一个主服务器。
  • REDIS_SLAVE,和REDIS_MASTER相对应,该状态表示客户端代表的是一个从服务器。
  • REDIS_PRE_PSYNC,表示客户端是一个低于2.8的从服务器,主服务器不能使用PSYNC与这个从服务器进行同步。
  • REDIS_LUA_CLIENT,表示客户端是一个专门处理LUA脚本的伪客户端。
  • REDIS_MONITOR,客户端正在执行MONITOR命令
  • REDIS_UNIX_SOCKET,服务器使用UNIX套接字来连接客户端。
  • REDIS_BLOCKED,客户端被BRPOP、BLPOP等命令阻塞。
  • REDIS_UNBLOCKED,客户端已经从REDIS_BLOCKED状态脱离。
  • REDIS_MULTI,客户端正在执行事务。
  • REDIS_DIRTY_CAS,表示事务正在使用WATCH命令监视的数据库键已经被修改。
  • REDIS_DIRTY_EXEC,事务在命令入队时出现了错误,REDIS_DIRTY_CAS和REDIS_DIRTY_EXEC表示事务的安全性已经被破坏,事务会执行失败。
  • REDIS_CLOSE_ASAP,输出缓冲区超出了服务器允许的范围,服务器在下一次执行serverCron函数时会关闭这个客户端。
  • REDIS_CLOSE_AFTER_REPLY,有用户对该客户端执行了CLIENT KILL命令。
  • REDIS_ASKING,客户端向集群节点发送了ASKING命令。
  • REDIS_FORCE_AOF,强制服务器将当前命令写入AOF文件。
  • REDIS_FORCE_REPL,强制主服务器将当前执行的命令复制给所有从服务器。
  • REDIS_MASTER_FORCE_REPLY,从服务器向主服务器发送REPLICATION ACK命令前,主服务器对应的客户端需要打开该标识。

输入缓冲区

querybuf属性,sds类型。缓存客户端的命令,缓冲区的大小根据内容的大小动态的扩大或缩小,但是最大大小不能超过1G,否则服务器会关闭客户端。
输出缓冲区

缓存服务器给客户端的回复,每个客户端有两个缓冲区,一个固定长度(默认16K),用来存储长度较小的回复,一个动态长度,用来回复长度比较大的命令,但是为了避免缓冲区过来占用太多资源,服务器使用两种模式来限制缓冲区大小:
1、硬性限制:当缓冲区大小超出硬性限制大小之后,服务器马上关闭客户端。
2、软性限制:当缓冲区大小超出软性限制大小之后,但没有超出硬性限制,服务器通过obuf_soft_limit_reached_time属性纪录客户端达到软性限制的起始时间,之后服务器会持续监视客户端,如果输出缓冲区一直超出软性限制,并且持续时间超过服务器设定的时长,那么服务器将关闭客户端;相反地如果输出缓冲区在指定时间内不再超出软性限制,那么客户端不会被关闭,并且obuf_soft_limit_reached_time属性值也会被清零。client-output-buffer-limit选项可以为普通客户端、从服务器客户端、执行发布与订阅功能的客户端设置不同的软性限制和硬性限制,该选项格式为client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>,以下是三个设置示例:
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
分别说明,对普通客户端不限制输出缓冲区大小;从服务器客户端硬性显示为256M,软性限制为64M,软性限制时长60s;发布订阅客户端硬性限制32M,软性限制8M,软性限制时长60s。

当前要执行的命令与命令参数

服务端对输入缓存区中的命令进行解析之后,把命令参数和命令参数个数分别保存在redisClient结构体的argv属性和argc属性。redisCommand结构对应命令,在redisCommand中会记录该命令执行的总次数和总时长,redisClient结构体中包含了一个redisCommand类型的属性cmd。在服务器维护了一个hash表保存所有命令,key为命令名,value为redisCommand结构。

身份验证标识

authenticated属性记录客户端是否通过了身份验证,0位通过,1已通过。当客户端未通过验证时服务器会拒绝该客户端除AUTH命令外的任何其它命令。

时间

客户端还保存几个跟时间相关的属性。

ctime:客户端创建的时间。

lastinteraction:客户端最后一次与服务器互动的时间。

obuf_soft_limit_reached_time:输出缓冲区第一次达到软性限制的时间。

关闭普通客户端
客户端状态会消耗服务端的内存资源和句柄资源,所以服务器在下列条件会关闭客户端:

  • 客户端进程退出或被杀死。
  • 客户端向服务器发送了不符合格式的命令。
  • 客户端称为CLIENT KILL命令的目标。
  • 用户为服务器设置了timeout选项,那么当客户端的空转时长超过timeout时,客户端会被关闭,不过也有例外,比如当客户端被BLPOP等命令阻塞或正在执行发布订阅命令,这时即使空转时间超过了timeout也不会关闭连接。
  • 客户端发送的命令请求的大小超出了输入缓冲区大小(默认1G)。
  • 客户端的命令回复大小超过了输出缓冲区的硬性限制,或者超出软性限制达到一定的时长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值