前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Redis设计与实现》读书笔记(十八) ——Redis客户端属性设计与原理

《Redis设计与实现》读书笔记(十八) ——Redis客户端属性设计与原理

作者头像
用户1327360
发布2018-03-07 16:01:32
1.2K0
发布2018-03-07 16:01:32
举报
文章被收录于专栏:决胜机器学习决胜机器学习

《Redis设计与实现》读书笔记(十八) ——Redis客户端属性设计与原理

(原创内容,转载请注明来源,谢谢)

一、概述

redis服务器是一对多服务器,多个客户端可以与一个服务器建立连接,并且分别发送请求,服务器接收请求并分别回复。通过使用I/O多路复用技术实现的文件事件处理器,redis服务器使用单线程单进程的方式来处理请求,并与多个客户端建立网络通信。

1、单个客户端状态结构存储

每个与服务器建立连接的客户端,服务器都为这些客户端建立相应的redis.h/redisClient结构,用于分别存储每个客户端的状态,这个结构保存客户端当前的信息,以及执行相关功能时候需要用到的数据结构,主要包括:

1)客户端信息

客户端套接字描述符,客户端名字,客户端标志值,客户端身份验证标志,客户端创建时间、最后一次与服务器通信时间、客户端输出缓冲区以及缓冲区大小超出服务器软性限制的时间。

2)客户端状态

客户端当前使用的数据库指针及数据库号码,客户端当前要执行的命令、命令参数、参数个数、实现命令的指针。

3)客户端用到的数据结构

客户端复制状态信息及复制所需的数据结构,客户端执行brpop、blpop等阻塞列表命令时用到的数据结构,客户端事务及watch用到的数据结构,客户端执行发布订阅功能用到的数据结构。

2、所有客户端存储

redis通过redisServer结构的clients属性,将所有的客户端结构进行存储,存储是采用链表的方式。如下:

         struct redisServer{
         //…其他内容
         list *clients;
         }

clients属性,以链表的形式,存储了所有的客户端状态,里面的每个元素都代表一个客户端,包含该客户端的诸如客户端信息、状态、使用的数据结构等全部信息。如下图所示:

二、客户端属性

客户端属性分为通用的和特定操作下的属性,特定操作如切换数据库、执行事务、watch等。这里重点学习通用属性。

主要用到的类型如下:

         typedef struct redisClient{
         //..其他内容
         int fd;
         robj *name;
         int flags;
         sds querybuf;
         robj **argv;
         int argc;
         struct redisCommand*cmd;
         char buf[REDIS_REPLY_TRUNK_BYTES];
         int bufpos;
         list *reply;
         int authenticated;
         time_t ctime;
         time_tlastinteraction;
         time_t obuf_soft_limit_reached_time;
         }redisClient;

1、套接字描述符

在redisClient里面,用int的方式记录当前使用的套接字描述符,属性名称是fd。

fd的值是-1或者大于-1的整数。当客户端是来自AOF文件或者Lua脚本,需要生成的临时的伪客户端,则值是-1,表示其不需要网络;正常的客户端值是大于-1的整数,这个值是redis客户端和redis服务器进行通信的描述符。

2、名字

客户端的名字属性名称是name,类型是redis的字符串对象。

默认情况下客户端没有名字,可以通过client setname设置名字,通过client list命令查看当前所有客户端的信息,如下是设置名字之后的:

如果没有设置名字,name是指向null的指针,设置之后则是redis字符串对象。

3、标志

客户端的标志记录客户端的角色,和当前客户端所处的状态,用int类型存储,属性名是flags。标志可以是单个的也可以是多个的二进制“或”。如flags = flag1 或者flags = flag1 | flag2 |flag3。

每个标志是一个常量,主要的如下:

1)主从复制期间,主服务器会成为从服务器的客户端,REDIS_MASTER表示客户端是主服务器,REDIS_SLAVE表示客户端是从服务器。

2)REDIS_PRE_PSYNC表示客户端是redis版本低于2.8的从服务器,主服务器不能用psync命令才进行复制。

3)REDIS_LUA_CLIENT表示lua脚本创建的伪客户端。

4)还有其他标志,最重要的是REDIS_UNBLOCKED,这标志标记redis已经从阻塞状态脱离出来,只有这样的客户端才会接收到服务器发送的信息。

5)REDIS_FORCE_AOF,这个标志也很特殊,默认情况下只有“写”相关的命令才会计入aof文件,但是存在个别命令,虽然不会影响到数据库的数据,但是会产生副作用,则需要用此标记,强制将结果写入aof。例如pubsub命令,会给所有订阅者发送信息;script load命令,加载脚本。

flags例子如下:

4、输入缓冲区

输入缓冲区保存客户端发送的命令请求,采用redis的sds类型存储,名称是querybuf。sds是简单动态字符串,是redis用来存储字符串对象值的结构。

输入缓冲区会根据输入的内容动态扩大或减小,但是不能超过1gb,否则redis会自动关闭该客户端。

输入命令set key value,querybuf的结果(缩略)如下:

5、命令与命令参数

当发送请求道querybuf后,redis会对命令进行分析,将命令参数保存到**argv,命令个数保存到argc。

argv是一个数组,每一项都是一个redis字符串对象,其中argv[0]是要执行的命令,后面的下标是传入的参数。argc则是记录数组argv的长度。

输入命令set key value,argc和argv的结果如下:

6、命令实现函数

分析完querybuf,并生成argc和argv后,redis将根据argv[0]的内容,确定相应的要实现的函数。

redis保存着一个数据字典,该字典存储着每个命令与其对应的redisCommand结构,键是sds结构的命令,值是对应的redisCommand结构。该字典也成为redis的命令表。

客户端的cmd属性,即分析完argv[0]后,从上述redis命令表中找到对应的结构,并用指针指向该结构。命令表的键不区分大小写,因此redis的命令也是不区分大小写的。

7、输出缓冲区

执行命令得到的回复,会保存在输出缓冲区中,每个客户端都有两个缓冲区,一个是固定大小的,另一个可变大小的。

固定大小的缓冲区由buf和bufpos两个属性组成,buf是一个数组,用于存储固定大小的返回值,默认大小是16kb;bufpos记录目前buf已经使用的字节数。固定大小缓冲区通常用于记录长度比较短的元素,如OK、短的字符串返回值、整数、错误回复等。

可变大小的缓冲区由链表组成,属性名是reply,链表内是一个或多个字符串对象组成。当回复的长度太长,则用可变大小缓冲区。另外,如果一开始用固定大小缓冲区,当记录过程中大小超过16kb,则会转换成可变大小缓冲区。

8、身份验证

redis用int记录是否验证身份,属性名是authenticated,0表示未通过验证,1表示已经通过验证。

当未验证身份,除了auth以外的命令,都会被redis服务器拒绝。

9、时间

redis共有3个属性记录客户端的时间相关的内容:ctime、lastinteraction、obuf_soft_limit_reached_time,类型都是time_t。

ctime记录客户端与redis服务器创建连接的时间,clientlist命令可以查看客户端连接的秒数,用age表示,单位是秒。

lastinteraction表示客户端与redis服务器最后一次交互的时间,可以是服务器发送信息给客户端的时间,也可以是客户端发送信息给服务器的时间。这个时间主要用来判断空转时间,即连接后没有操作的时间,client list可以查看空转时间,用idle表示,单位是秒。

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

——written by linhxx 2017.09.08

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 决胜机器学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档