redis-客户端

345 阅读6分钟

客户端属性

客户端状态包含的属性可以分为两类:

一类是比较通用的属性, 这些属性很少与特定功能相关, 无论客户端执行的是什么工作, 它们都要用到这些属性。 另外一类是和特定功能相关的属性, 比如操作数据库时需要用到的 db 属性和 dictid 属性, 执行事务时需要用到的 mstate 属性, 以及执行 WATCH 命令时需要用到的 watched_keys 属性, 等等。 本章将对客户端状态中比较通用的那部分属性进行介绍, 至于那些和特定功能相关的属性, 则会在相应的章节进行介绍

typedef struct redisClient {

    // ...

    int fd;

    // ...

} redisClient;

根据客户端类型的不同, fd 属性的值可以是 -1 或者是大于 -1 的整数:

伪客户端(fake client)的 fd 属性的值为 -1 : 伪客户端处理的命令请求来源于 AOF 文件或者 Lua 脚本, 而不是网络, 所以这种客户端不需要套接字连接, 自然也不需要记录套接字描述符。 目前 Redis 服务器会在两个地方用到伪客户端, 一个用于载入 AOF 文件并还原数据库状态, 而另一个则用于执行 Lua 脚本中包含的 Redis 命令。 普通客户端的 fd 属性的值为大于 -1 的整数: 普通客户端使用套接字来与服务器进行通讯, 所以服务器会用 fd 属性来记录客户端套接字的描述符。 因为合法的套接字描述符不能是 -1 , 所以普通客户端的套接字描述符的值必然是大于 -1 的整数。 执行 CLIENT_LIST 命令可以列出目前所有连接到服务器的普通客户端, 命令输出中的 fd 域显示了服务器连接客户端所使用的套接字描述符:

  • addr:地址及端口
  • fd:套接字描述符
  • name: 可以使用client setname 设置某个链接的名称
  • age: 链接的时间,单位秒
  • idle:空闲时间,单位秒
  • flags:记录了客户端的角色(role)
# 客户端是一个主服务器
REDIS_MASTER

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

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

# 客户端是一个从服务器,并且版本低于 Redis 2.8
REDIS_SLAVE | REDIS_PRE_PSYNC

# 这是专门用于执行 Lua 脚本包含的 Redis 命令的伪客户端
# 它强制服务器将当前执行的命令写入 AOF 文件,并复制给从服务器
REDIS_LUA_CLIENT | REDIS_FORCE_AOF | REDIS_FORCE_REPL

输入缓冲区

typedef struct redisClient{
    sds querybuf;
}redisClient
  • 输入缓存区的大小会根据输入内容动态的缩小或者扩大,但它的最大大小不能超过1GB,否则服务器将关闭这个客户端。

命令与参数

typedef struct redisClient{
    robj **argv;
    int argc;
}redisClient
  • argv属性是一个数组,数组中的每个项都是一个字符串对象,其中argv[0]是要执行的命令,而之后的其他项则传给命令的参数。
  • argc属性则负责记录argv数组的长度

命令的实现函数

举例命令:set key value 直接看图:

输出缓冲区

执行客户端的回复会保存在客户端状态的输出缓冲区里面,每个客户端都有两个输出缓冲区可用,一个缓存区是固定大小,另一个缓冲区的大小是可变的

  • 固定大小的缓冲区用于保存那些长度比较小的回复,比如ok、简短的字符串值、整数值、错误回复等等。
  • 可变大小的缓冲区用于保存那些长度比较大的回复,比如一个非常长的字符串值,一个由很多项组成的列表,一个包含了很多元素的集合等等。
typedef struct redisClient{
    char buf[REDIS_REPLY_CHUNK_BYTES];
    
    int bufpos;
    
    list *reply;
}
  • buf数组,REDIS_REPLY_CHUNK_BYTES默认值16*1024,大小为16KB
  • bufpos记录buf数组使用字节的数量
  • reply是一个链表

固定缓冲区

可变缓冲区

身份验证

  • authenticated:0未验证,1已验证通过
  • requirepass:配置此属性是的打开验证

客户端的创建与关闭

什么时候客服端关闭

  • 客户端退出或者被杀死
  • 客户端发送不符合协议格式的命令,被服务端关闭
  • 被 client kill
  • 服务器设置了timeout
  • 输入缓冲区大于限制大小,默认1GB
  • 回复的命令大于输入缓冲区的限制

配置

  • clinet-output-buffer-limit normal 0 0 0 :表示不限制客户端的输出缓冲区大小
  • clinet-output-buffer-limit slave 256mb 64mb 60 :硬性设置256MB,软性设置为64MB,软性限制的时长60秒
  • clinet-output-buffer-limit pubsub 32mb 8mb 60 :发布与订阅硬性限制32MB,软性限制8MB,软性相纸的时长为60秒

伪客户端

  • lua脚本
  • AOF文件:服务器载入AOF文件时

重点

  • 服务器状态结构使用 clients 链表连接起多个客户端状态, 新添加的客户端状态会被放到链表的末尾。
  • 客户端状态的 flags 属性使用不同标志来表示客户端的角色, 以及客户端当前所处的状态。
  • 输入缓冲区记录了客户端发送的命令请求, 这个缓冲区的大小不能超过 1 GB 。 命令的参数和参数个数会被记录在客户端状态的 argv 和 argc 属性里面, 而 cmd 属性则记录了客户端要执行命令的实现函数。
  • 客户端有固定大小缓冲区和可变大小缓冲区两种缓冲区可用, 其中固定大小缓冲区的最大大小为 16 KB , 而可变大小缓冲区的最大大小不能超过服务器设置的硬性限制值。
  • 输出缓冲区限制值有两种, 如果输出缓冲区的大小超过了服务器设置的硬性限制, 那么客户端会被立即关闭; 除此之外, 如果客户端在一定时间内, 一直超过服务器设置的软性限制, 那么客户端也会被关闭。
  • 当一个客户端通过网络连接连上服务器时, 服务器会为这个客户端创建相应的客户端状态。 网络连接关闭、 发送了不合协议格式的命令请求、 成为 CLIENT_KILL 命令的目标、 空转时间超时、 * * 输出缓冲区的大小超出限制, 以上这些原因都会造成客户端被关闭。 处理 Lua 脚本的伪客户端在服务器初始化时创建, 这个客户端会一直存在, 直到服务器关闭。
  • 载入 AOF 文件时使用的伪客户端在载入工作开始时动态创建, 载入工作完毕之后关闭。