Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复。

通过使用由I/O多路复用技术实现的文件事件处理器,Redis服务器使用单线程单进程的方式处理命令请求,并于多个客户端进行网络通信。

每个与服务器进行连接的客户端,服务端都为这些客户端建立相应的redisClient结构(客户端状态),保存客户端当前的状态信息,以及执行相关功能时需要用到的数据结构。

Redis服务器状态结构的clients属性是一个链表,这个链表保存了所有与服务器连接的客户端的状态结构,对客户端执行批量操作,或者查找某个指定的客户端,都可以通过遍历clients链完成。

struct redisServer{
//一个链表,保存了所有客户端状态
list *clients;
}

1、客户端状态的fd属性记录了客户端正在使用的套接字描述符

typedef struct redisClient{
int fd;
} redisClient;

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

2、默认情况下一个连接到服务器的客户端是没有名称的, 可以使用Client setname 命令为客户端设置一个名称。

3、客户端的标志属性flags记录了客户端角色(role),以及客户端状态

typedef struct redisClient{
int flag;
} redisClient;

在主从服务器进行复制操作时,主服务器会成为从服务器的客户端,而从服务器也会成为主服务器的客户端。

REDIS_MASTER 客户端是一个主服务器

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

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

REDIS_SLAVE | REDOS_PRE_PSYNC 客户端是一个从服务器,并且版本低于REDIS2.8

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

4、客户端状态的输入缓冲区用户保存客户端发送的命令请求:

typedef struct redisClient {
sds querybuf;
} redisClient;

5、在服务器将客户端发送的命令请求保存在客户端状态的querybuf属性后,服务器将对命令请求的内容进行分析,并将得出的命令参数以及命令参数的个数分别保存到客户端状态的argv属性和argc属性

typedef struct redisClient{
robj **argv;
int argc;
} redisClient;

argv属性是一个数组,数组的每个项都是一个字符串队形,其中avgv[0]是要执行的命令,其之后的其他项都是传给命令的参数。

6、当服务器从协议内容中分析并得出argv属性和argc属性的值之后,服务器将根据项argv[0]的值,在命令表中查找命令所对应的实现函数。

命令表是一个字典表,字典的键是一个SDS结构,保存了命令的名字,字典值是命令的名字,字典值是命令所对应的redisCommand结构,这个结构保存了命令的实现函数、命令的标志、命令应该给定的参数个数、命令的总执行次数和总耗时长等统计信息。

当程序在命令表中成功找到argv[0]所对应的redisCommand结构时,它会将客户端状态的cmd指针指向这个结构:

typedef struct redisClient{
struct redisCommand *cmd;
} redisClient;

之后,服务器就可以使用cmd属性所指向的redisCommand结构,以及argv、argc属性中保存的命令参数信息,调用命令实现函数,执行客户端指定的命令。

7、执行命令所得的命令回复会被保存在客户端状态的输出缓冲区里面,每个客户端有两个输出缓冲区可以用,一个缓冲区的大小是固定的,一个大小是可变的。

固定大小的缓冲区用于保存那些长度比较小的回复,可变大小的缓冲区用于保存耐饿长度比较大的回复。

客户端的固定大小缓冲区由buf和bufpos两个属性组成

typedef struct redisClient{
char buf[REDIS_REPLY_CHUNK_BYTES];//REDIS_REPLY_CHUNK_BYTES 默认16 *1024 也就是说固定缓冲区默认 16k
int bufpos;//记录已使用的字节数量
} redisClient;

8、身份认证

客户端状态的authenticated属性用于记录客户端是否通过了身份验证:

typedef struct redisClient{
int authenticated;
} redisClient;

authenticated属性仅在服务器启用了身份验证功能的时候使用,如果服务器没有启用的话,即使为0也不会拒绝客户端的命令请求。

9、时间

typedef struct redisClient{
time_t ctime;//创建客户端的时间 连接服务器时长(秒)
time_t lastinteraction;//最后一次与服务器互动时间,计算客户端空转时间
//记录缓冲区第一次到达软性限制的时间
time_t obuf_soft_limit_reached_time;
} redisClient;

如果客户端是通过网络连接于服务器进行连接的普通客户端,那么客户端使用connect函数连接到服务器时,服务器就会调用连接事件处理器,为客户端创建相应的客户端状态,并将这个新的客户端状态添加到服务器状态结构clients链表的末尾。

普通客户端可以因为多种原因而被关闭:

客户端进程退出或者被杀死,那么客户端与服务端的网络连接被关闭。

如果客户端向服务端发送了带有不符合协议的命令请求,那么这个客户端也会被关闭。

如果客户端成为了CLIENT KILL命令的目标,那么它也会被关闭。

如果服务端设置了timeout配置项,那么客户端的空转事件超过timeout现象设置的值时,客户端被关闭。

如果客户端发送的命令请求的大小超过了输入缓冲区的限制大小(默认1G),那么客户端会被服务器关闭。

如果要发送给客户端的命令回复的大小超过了输出缓冲区的限制大小,那么这个客户端会被服务器关闭。

服务器使用两种模式来限制客户端输出缓冲区的大小:

1、硬性限制,如果输出缓冲区的大小超过了硬性限制所设置的大小,那么服务器立即关闭客户端。

2、软性限制,如果输出缓冲区的大小超过了软性限制设置的大小,但没有超过硬性设置的大小,obuf_soft_limit_reached_time属性记录下客户端达到软性限制的起始事件,之后服务器会继续监视客户端,如果输出缓冲区的大小一直超出软性限制,并且持续时间超过服务器设置的时长,那么服务器将关闭客户端。

服务端会在初始化时创建负责执行Lua脚本中包含redis命令的伪客户端,并将这个伪客户端关联在服务器状态结构的lua_client属性中:

struct redisServer{
redisClient *lua_client;
}

lua_client 伪客户端在服务器运行的整个声明周期中会一直存在,只有服务器关闭时,这个客户端才会关闭。

服务器在载入AOF文件时,会创建用于执行AOF文件的Redis命令的伪客户端,并在载入完成之后,关闭伪客户端。


每天学一点,总会有收获。

说明:尊重作者知识产权,文中内容参考《Redis设计与实现》,仅在此做学习与大家分享。


Redis学习笔记(十) 客户端的更多相关文章

  1. Redis学习笔记十:独立功能之监视器

    通过执行 monitor 命令可以让客户端自己变成一个监视器,实时接收并打印当前处理的命令请求的相关信息. 127.0.0.1:6379> monitor OK 1451752646.83727 ...

  2. redis 学习笔记(6)-cluster集群搭建

    上次写redis的学习笔记还是2014年,一转眼已经快2年过去了,在段时间里,redis最大的变化之一就是cluster功能的正式发布,以前要搞redis集群,得借助一致性hash来自己搞shardi ...

  3. redis 学习笔记-cluster集群搭建

    一.下载最新版redis 编译 目前最新版是3.0.7,下载地址:http://www.redis.io/download 编译很简单,一个make命令即可,不清楚的同学,可参考我之前的笔记: red ...

  4. Redis学习笔记~目录

    回到占占推荐博客索引 百度百科 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合). ...

  5. Redis学习笔记4-Redis配置详解

    在Redis中直接启动redis-server服务时, 采用的是默认的配置文件.采用redis-server   xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务.按照本Redi ...

  6. Redis学习笔记7--Redis管道(pipeline)

    redis是一个cs模式的tcp server,使用和http类似的请求响应协议.一个client可以通过一个socket连接发起多个请求命令.每个请求命令发出后client通常会阻塞并等待redis ...

  7. (转)redis 学习笔记(1)-编译、启动、停止

    redis 学习笔记(1)-编译.启动.停止   一.下载.编译 redis是以源码方式发行的,先下载源码,然后在linux下编译 1.1 http://www.redis.io/download 先 ...

  8. Redis 学习笔记4: Redis 3.2.1 集群搭建

    在CenOS 6.7 linux环境下搭建Redis 集群环境 1.下载最新的Redis版本 本人下载的Redis版本是3.2.1版本,下载之后,解压,编译(make): 具体操作可以参考我的博文:R ...

  9. Redis学习笔记(2)——Redis的下载安装部署

    一.下载Redis Redis的官网下载页上有各种各样的版本,如图 但是官网下载的Redis项目不正式支持Windows.如果需要再windows系统上部署,要去GitHub上下载.我下载的是Redi ...

  10. Redis学习笔记(1)- CentOS 6.4 安装Redis

    Redis学习笔记(1)- CentOS 6.4 安装Redis 2013.10.13     学习环境 vm 10.1 + 默认.新装的干净 CentOS 6.4  64BIT系统     准备 1 ...

随机推荐

  1. 关于virtual box 虚拟机使用

    关于virtual box的使用,如果想用共享文档:比如当前系统为Ubuntu,virtual box安装了win7,win7与Ubuntu之间的文件使用,就可以利用 共享文档 这个便利的功能—— 在 ...

  2. Windows 版本 Enterprise、Ultimate、Home、Professional

    关于Windows 的安装光盘版本很多种,很多人不知道选择哪些. Ultimate 旗舰版,VISTA开始有了这个级别,是最全最高级的,一般程序开发的电脑,玩游戏的电脑,建议用它,不过对配置稍有一些要 ...

  3. Spring5参考指南:Bean的生命周期管理

    文章目录 Spring Bean 的生命周期回调 总结生命周期机制 startup和Shutdown回调 优雅的关闭Spring IoC容器 Spring Bean 的生命周期回调 Spring中的B ...

  4. 【Linux常见问题】CentOS 7 root用户密码忘记,找回密码方法

    1.开机按esc 2.选择CentOS Linux (3.10.0-693.......)     按 e 键: 3.光标移动到 linux 16 开头的行,找到 ro 改为 rw init=sysr ...

  5. 快速上手最新的 Vue CLI 3

    翻译:疯狂的技术宅 原文:blog.logrocket.com/getting-sta- 概要:本文将指导你快速上手 Vue CLI 3,包括最新的用户图形界面和即时原型制作功能的使用步骤. 介绍 尤 ...

  6. Failed building wheel for cytoolz

    2019独角兽企业重金招聘Python工程师标准>>> 当我使用 pip instlal cytoolz 时,  报以下错误: error: Microsoft Visual C++ ...

  7. 在Jetson TX2上安装caffe和PyCaffe

    caffe是Nvidia TensorRT最支持的深度学习框架,因此在Jetson TX2上安装caffe很有必要.顺便说一句,下面的安装是支持python3的. 先决条件 在Jetson TX2上完 ...

  8. 7) 项目准备流程 和 django权限六表

    一.项目准备 1. 创建django项目 2. 创建数据库 —— init文件中声明mysql —— settings中配置数据库 import pymysql pymysql.install_as_ ...

  9. vue获取当前时间 实时刷新

    需求:获取当前系统时间,在页面上展示 年月日 时分秒 ,并且实时刷新,和系统时间保持一致 第一步:在deta 里面声明两个变量第二步:把时间调用写在created() 生命周期里面,进入页面就需要调用 ...

  10. 精通awk系列文章

    精通awk系列文章 我录制了两个awk相关的视频教程: Awk经典实战案例精讲 精通awk精品课程:awk从入门到精通 1.安装新版本的gawk 2.本教程测试所用示例文件 3.铺垫知识:读取文件的几 ...