Redis 服务器是典型的一对多服务器程序,通过使用由 I/O 多路复用技术实现的文件事件处理器,服务器使用单线程单进程的方式来处理命令请求,并与多个客户端进行网络通信
redis.h/redisClient 结构保存了客户端当前的状态信息,以及执行相关功能需要用到的数据结构:
客户端的套接字描述符
客户端的名字
客户端的标志值
指向客户端正在使用的数据库的指针,数据库的号码
客户端当前执行的命令、命令的参数、命令参数的个数、指向命令实现函数的指针
客户端的输入缓冲区和输出缓冲区
客户端的复制状态信息、进行复制需要的数据结构
客户端执行 BRPOP、BLPOP 等列表阻塞命令需要的数据结构
客户端的事务状态、执行 WATCH 命令的数据结构
客户端执行发布与订阅功能的数据结构
客户端的身份验证标志
客户端的创建时间、客户端和服务器最后一次通信的时间、客户端的输出缓冲区大小超过软性限制的时间
服务器状态结构的 clients 属性是一个链表,保存了所有与服务器相连接的客户端的状态结构
分为两类:
客户端状态 fd 属性记录套接字描述符,取值为 -1 或大于 -1 的整数
伪客户端的 fd 属性为 -1:处理的命令请求来源于 AOF 或者 Lua 脚本
普通客户端的 fd 属性为大于 -1 的整数
默认情况下客户端是没有名字的,名字记录在客户端状态的 name 属性,可以使用 clint setname 为当前客户端设置名字
没有名字时 name 属性指向 NULL 指针;设置了名字将指向一个字符串对象
flags 记录了客户端的角色及客户端所处的状态
可以是单个标志
也可以是多个二进制或
每个标志使用一个常量表示,一部分标志记录了客户端的角色
AOF 持续化只会将修改了数据库的命令写入 AOF 文件,但 PUBLIS 命令是向频道的订阅者发送消息,而接收消息的客户端状态会因此改变,需要 REDIS_FORCE_AOF 标志强制写入;SCRIPT LOAD 修改了服务器的状态,同理需要 REDIS_FORCE_AOF 标志
sds querybuf 属性即客户端状态的输入缓冲区,保存客户端发送的命令请求,大小会根据输入内容动态变化,但最大不能超过 1 GB,否则服务器会关闭次客户端
服务器对命令请求的内容分析后得出的命令参数及个数将被保存到客户端状态的 argv、argc 属性
服务器根据 argv[0] 的值在命令表中查找命令对应的命令实现函数
一个字典,键是 SDS 结构,保存名字,值是命令对应的 redisCommand 结构,保存了实现函数、命令标志等等的统计信息
程序在命令表中找到 argv[0] 所对应的 redisCommand 结构,则将 cmd 指针指向这个结构
针对命令表的查找操作不区分输入字母的大小写
执行命令所得的回复保存在客户端状态的输出缓冲区,每个客户端都有两个输出缓冲区可用,一个固定一个变化
固定大小缓冲区由 buf、bufpos 组成
REDIS_REPLY_CHUNK_BYTES 默认为 16 * 1024 ,即 16 KB
当 buf 数组使用完或者回复太大而没办法放进 buf 数组时,服务器则使用可变大小缓冲区
可变缓冲区由 reply 链表和一个或多个字符串组成,通过链表来连接多个字符串对象
客户端状态的 authenticated 属性记录了客户端是否通过身份验证
如果服务器没有启用身份验证,即使 authenticated 为 0 也不会拒绝,由 requirepass 设置
ctime:创建客户端的时间,Client list 的 age 域记录
lastinteraction:客户端与服务器最后一次进行互动的时间,可以指某一方对另一方的行为,不特定客户端或者服务器
obuf_soft_limit_reached_time:记录输出缓冲区第一次到软性限制的时间
如果客户端是通过网络连接与服务器进行连接的普通客户端,则在客户端使用 connect 函数连接到服务器时,服务器会调用连接事件处理器为客户端创建客户端状态,并加入到服务器状态 clients 链表末尾
关闭原因:
客户端进程退出或被杀死
客户端发送带有不符合协议格式的命令请求
客户端成为 client kill 命令的目标
服务器配置了 timeou 选项,空转时间超过则关闭
命令请求大小超过输出缓冲区限制
回复超过输出缓冲区限制
可变大小缓冲区理论上任意长,但为了避免回复过大,会时刻检查客户端的输出缓冲区大小,超过时执行限制
进行设置
lua_client 关联负责执行 Lua 脚本中的 Redis 命令的伪客户端,直到服务器关闭此客户端才会被关闭
在载入 AOF 文件创建,载入完成后关闭