Redis中的客户端(一)

客户端

概述

Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复。通过使用由IO多路复用技术实现的文件事件管理器,Redis服务器使用单线程单进程的方式来处理命令请求,并与多个客户端进行网络通信。对于每个与服务器进行连接的客户端,服务器都为这些客户端建立了相应的redis.h/redisClient结构(客户端状态),这个结构保存了客户端当前的状态信息,以及执行相关功能时需要用到的数据结构,其中包括:

  • 1.客户端的套接字描述符
  • 2.客户端的名字
  • 3.客户端的标志值(falg)
  • 4.指向客户端正在使用的数据库的指针,以及该数据库的号码
  • 5.客户端当前要执行的命令、命令的参数、命令参数的个数、以及指向命令实现函数的指针
  • 6.客户端的输入缓冲区和输出缓冲区
  • 7.客户端的复制状态信息,以及进行复制所需的数据结构
  • 8.客户端执行BRPOP、BLPOP等列表阻塞命令时使用的数据结构
  • 9.客户端的事务状态。以及执行WATCH命令时用到的数据结构
  • 10.客户端执行发布与订阅功能时用到的数据结构
  • 11.客户端的身份验证标志
  • 12.客户端的创建事件,客户端和服务器最后一次通信的时间,以及客户端的输出缓冲区大小超出软性限制(soft limit)的时间
    Redis服务器状态结构的clients属性是一个链表,这个链表保存了所有与服务器连接的客户端的状态结构,对客户端执行批量操作,或者查找某个指定的客户端,都可以通过遍历clients链表来完成:
struct redisServer {
 // ...
 
 // 一个链表,保存了所有客户端状态
 list *clients;
 
 // ...
}

例子

  • 举个例子,如图展示了一个与三个客户端进行连接的服务器
    在这里插入图片描述
  • 如图展示了这个服务器的clients链表的样子在这里插入图片描述

客户端属性

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

  • 1.一类是比较通用的属性,这些属性很少与特定功能相关,无论客户端执行的是什么工作,它们都要用到这些属性
  • 2.另外一类是和特定功能相关的属性,比如操作数据库时需要用到的db属性和dictid属性,执行事务时需要用到的mstate属性,以及执行WATCH命令时需要用到的watched_keys属性等等。

套接字描述符

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

typedef struct redisClient {
 // ...
 int fd;
 // ...
}redisClient;

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

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

执行CLIENT list命令可以列出目前所有连接到服务器的普通客户端,命令输出中的fd域显示了服务器连接客户端所使用的套接字描述符:

127.0.0.1:6379> client list
id=4 addr=127.0.0.1:61899 fd=9 name= age=27 idle=22 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client
id=5 addr=127.0.0.1:61921 fd=10 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client

名字

在默认情况下,一个连接到服务器的客户端是没有名字的。
比如在下面展示的CLIENT list命令示例中,两个客户端的name域都是空白的:

127.0.0.1:6379> client list
id=4 addr=127.0.0.1:61899 fd=9 name= age=27 idle=22 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client
id=5 addr=127.0.0.1:61921 fd=10 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client

使用CLIENT setname 命令可以为客户端设置一个名字,让客户端的身份变得更清晰。

127.0.0.1:6379> CLIENT setname testName1
OK
127.0.0.1:6379> client list
id=4 addr=127.0.0.1:61899 fd=9 name=testName1 age=439 idle=6 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client
id=5 addr=127.0.0.1:61921 fd=10 name= age=421 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client

其中第一个客户端的名字设置为了testName1,第二个客户端没有进行设置。客户端的名字记录在客户端状态的name属性里面:

typedef struct redisClient {
 // ...
 robj *name;
 // ...
}redisClient

如果客户端没有为自己设置名字,那么相应客户端状态的name属性指向NULL指针,相反地,如果客户端为自己设置了名字,那么name
属性将指向一个字符串对象,而该对象就保存着客户端的名字。

例子
  • 举个例子。如图展示了一个客户端状态示例,根据name属性显示,
    客户端的名字为"testName1"在这里插入图片描述

标志

客户端的标志属性flags记录了客户端的角色(role),以及客户端目前所处的状态:

typedef struct redisClient {
 // ...
 int flags;
 // ...
}redisClient

flags属性的值可以是单个标志:flags = < flag >,
也可以是多个标志的二进制或,比如:flags = < flag1 > | < flag2 > | …
每个标志使用一个常量表示,一部分标志记录了客户端的角色:

  • 1.在主从服务器进行复制操作时,主服务器会称为从服务器的客户端,而从服务器也会成为主服务器的客户端。REDIS_MASTER标志表示客户端代表的是一个主服务器,REDIS_SLAVE标志客户端代表的是一个从服务器。
  • 2.REDIS_PRE_PSYNC标志表示kk而护短代表的是一个版本低于Redis2.8的从服务器,主服务器不能使用PYSNC命令与这个从服务器进行同步,这个标志只能在REDIS_SLAVE标志处于打开状态时使用
  • 3.REDIS_LUA_CLIENT标识表示客户端是专门用于处理Lua脚本里面包含的Redis的伪客户端。

而另一部分标志则记录了客户端目前所处的状态:

  • 1.REDIS_MONITOR标志表示客户端正在执行MONITOR命令
  • 2.REDIS_UNIX_SOCKET标志表示服务器使用UNIX套接字来连接客户端
  • 3.REDIS_BLOCKED标志表示客户端正在被BRPOP、BLPOP等命令阻塞
  • 4.REDIS_UNBLOCKED标志表示客户端已经从REDIS_BLOCKED标志所表示的阻塞状态中脱离出来,不再阻塞。REDIS_UNBLOCKED标志只能在REDIS_BLOCKED标志已经打开的情况下使用
  • 5.REDIS_MULTI标志表示客户端正在执行事务
  • 6.REDIS_DIRTY_CAS标志表示事务使用WATCH命令监视的数据库键已经被修改了
  • 7.REDIS_DIRTY_EXEC标志表示事务在命令入队时出现了错误,以上两个标志都表示事务的安全性已经被破坏,只要这两个标记中的任意一个被打开,EXEC命令必然会执行失败。这两个标志只能在客户端打开了REDIS_MULTI标志的情况下使用
  • 8.REDIS_CLOSE_ASAP标志表示客户端的输出缓冲区大小超出了服务器允许的范围,服务器会在下一次执行serverCron函数时关闭这个客户端,以免服务器的稳定性受到这个客户端影响。积存在输出缓冲区中的所有内容会直接被释放,不会返回给客户端。
  • 9.REDIS_CLOSE_AFTER_REPLY标志表示有用户对这个客户端执行了CLIENT KILL命令,或者客户端发送给服务器的命令请求中包含了错误的协议内容。服务器会将客户端积存z在输出缓冲区中的所有内容发送给客户端,然后关闭客户端
  • 10.REDIS_FORCE_AOF标志强制服务器将当前执行的命令写入到AOF文件里面,REDIS_FORCE_REPL标志强制主服务器将当前执行的命令复制给所有从服务器。执行PUBSUB命令会使客户端打开REDIS_FORCE_AOF标志,执行SCRIPT LOAD命令会使客户端打开REDIS_FORCE_AOF标志和REDIS_FORCE_REPL标志
  • 11.在主从服务器进行命令传播期间,从服务器需要向主服务器发送REPLICATION ACK命令,在发送这个命令之前,从服务器必须打开主服务器对应的客户端的REDIS_MASTER_FORCE_REPLY标志,否则发送操作会被拒绝执行
PUBSUB命令和SCRIPT LOAD命令的特殊性

通常情况下,Redis只会将那些对数据库进行了修改的命令写入到AOF文件,并复制到各个从服务器。如果一个命令没有对数据库j进行任何修改,那么它就会被认为是只读命令,这个命令不会被写入到AOF
文件,也不会被复制到从服务器。以上规则适用于绝大部分Redis命令,但PUBSUB命令和SCRIPT LOAD命令是其中的例外。PUBSUB命令虽然没有修改数据库,但PUBSUB命令向频道的所有订阅者发送消息
这一行为带有副作用,接收到消息的所有客户端的状态都会因为这个命令而改变。因此,服务器需要使用REDIS_FORCE_AOF标志,强制将这个命令写入AOF文件,这样在将来载入AOF文件时,服务器就可以再次
执行相同的PUBSUB命令,并产生相同的副作用。SCIRPT LOAD命令的情况与PUBSUB命令类似:虽然SCRIPT LOAD命令没有修改数据库,但它修改了服务器状态,所以它是一个带有副作用的命令,服务器
需要使用REDIS_FORCE_AOF标志,强制将这个命令写入AOF文件,使得将来在载入AOF文件时,服务器可以产生相同的副作用。另外,为了让主服务器和从服务器都可以正确地载入SCRIPT LOAD命令指定的脚本,
服务器需要使用REDIS_FORCE_REPL标志,强制将SCIRPT LOAD命令复制给所有从服务器

例子
  • 举个flags属性的例子:
# 客户端是一个主服务器
REDIS_MASTER
# 客户端正在被列表命令阻塞
REDIS_BLOCKED
# 客户端正在执行事务,但事务的安全性已被破坏
REDIS_MULTI | REDIS_DIRTY_CAS
# 客户端是一个从服务器,并且版本低于Redis2.8
REDIS_SLAVE | REDIS_PRE_PSYNC
# 这是专门用于执行Lua脚本包含的Redis命令的伪客户端
# 它强制服务器将当前的命令写入AOF文件,并复制给从服务器
REDIS_LUA_CLIENT | REDIS_FORCE_AOF | REDIS_FORCE_REPL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/493746.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ explicit隐式类型转换

单参数构造函数支持隐式类型的转换 什么意思&#xff1f; 简单来理解就是&#xff1a; 一个类对象的构造函数的参数只有一个&#xff0c;就可以直接进行赋值传参 例如构造函数的参数为int&#xff0c;且只有一个int 就可以直接将int类型的整型数据转换成类对象 也就是说从int类…

MySQL中的日历/时间/时间戳

一&#xff0c;日历 MySQL 使用通常所说的 proleptic 阳历。 每个将日历由朱利安改为阳历的国家在改变日历期间都不得不删除至少10天。 为了了解其运作&#xff0c;让我们看看1582年10月&#xff0c;这是由朱利安日历转换为阳历的第一次: 周一 周二 周三 周四 周五 周六…

海外媒体宣发:企业最牛出海最巨有“料”的几个新闻媒体

海外媒体宣发&#xff1a;企业最牛出海最巨有“料”的几个新闻媒体 1.雅虎财经&#xff08;Yahoo Finance&#xff09;雅虎网&#xff08;英文名字&#xff1a;Yahoo&#xff0c;NASDAQ&#xff1a;YHOO&#xff09;是美国有名的互联网技术门户网&#xff0c;都是20世纪初互联…

充钱也不能任性,今天用百度AI又骂街了

今天在用文心一言的时候又翻车了&#xff0c;应该是又骂街了。 cao&#xff0c;充钱也不能任性啊&#xff0c;不能手贱去看百度的新功能&#xff0c;垃圾的一批。 本来付费用了用4.0&#xff0c;感觉Chat功能还是可以的&#xff0c;不论是简单的代码&#xff0c;还是一些通用的…

抖音电商“达人客服”产品上线啦!超多作者邀你一起“321上客服”!

有问题别自己克服&#xff0c;来抖音电商找“达人客服” 当代年轻人购物&#xff0c;正在从机智省变成理智购。越来越多的人在达人直播间购物&#xff0c;看重的不止是优惠力度&#xff0c;还有服务保障。 为了帮助达人更好地服务用户&#xff0c;抖音电商上线了「达人客服」…

MySQL数据库------------探索高级SQL查询语句(一)

目录 一、常用查询 1.1按关键字排序 1.2简单的select条件查询(where) 二、排序 2.1升序排列 2.2降序排序 三、order by 查询结果排序 ①order by还可以结合where进行条件过滤&#xff0c;筛选地址是哪里的学生按分数降序排列 ②查询学生信息先按hobbyid降序排列&#…

如何解决Modbus转Profinet网关通信不稳定或数据丢失问题

接到现场反映&#xff0c;在配置Modbus转Profinet网关时&#xff0c;出现Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;通信不稳定或数据丢失的问题&#xff0c;就这个问题特做出答疑。 解决Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;通信不稳定或数据…

【区块链】C语言编程实现三叉Merkle树

目录 1. Merkle树简介2. 构建Merkle树3. 生成SPV路径4. 验证SPV路径5. 三叉Merkle树创建、SPV生成及验证总程序6. 程序运行结果 1. Merkle树简介 如上图所示&#xff0c;Merkle 树的叶子节点为交易序列&#xff0c;对每一笔交易进行 Hash&#xff08;SHA 256算法&#xff09; 之…

STM32F10X开发环境的搭建

一、keil软件安装 找到keil软件包&#xff0c;解压缩&#xff0c;找到keil5安装软件&#xff1a; 鼠标右键选择以管理员权限运行。点击next&#xff0c;直到安装结束。 安装完成后在桌面会出现keil5软件图标&#xff1a; 然后再安装相应的芯片支持包&#xff1a;我们用的是stm…

C语言:文件操作的详解(看完一定有更深刻的理解)

目录 前言 程序文件 文件的打开和关闭 流 标准流 文件的顺序读写 写文件 fputc函数 fputs函数 fprintf函数 读文件 fgetc函数 fgets函数 fscanf函数 printf/fprintf/sprintf scanf/fscanf/sscanf 文件的随机读写 fseek函数 ftell函数 rewind函数 大多数人用…

【数据库管理操作】Mysql 创建学生数据库及对数据表进行修改

MySQL 创建学生成绩数据库 1.创建数据库 create database studentscore;创建完成之后&#xff0c;如果需要使用该数据&#xff0c;使用use命令 use studentscore;创建表前查看当前数据库中包含的表 show tables; 2.创建bclass表 create table bclass( class_id char(8) …

深度学习入门1——Optimization

Methods of optimization Stochastic Gradient Descent (SGD) use mini-batch (32/64/128) to do gradient descent SGD Momentum continue moving in the general direction as the previous iterations Build up “velocity” as a running mean of gradients Rho giv…

全国河流湖库公开数据及应用实践

关于全国河流湖口的数据&#xff0c;通常指的是各条河流流入湖泊或海洋的位置及其相关的水文、地理信息。这类数据包括但不限于以下几个方面&#xff1a; 1. 地理位置&#xff1a;每条河流的出海口或流入湖泊的具体经纬度坐标。 2. 水文特征&#xff1a;如湖口水位、流量、径…

【数据库】表的约束

目录 一、非空约束 二、主键约束 三、外键约束 四、检查约束 五、唯一性约束 一、非空约束 每个字段都要有一个是否为nul值的选择&#xff0c;这就是对数据表中将来的数据提出的约束条件。null(允许空值)&#xff1a;表示数值未确定&#xff0c;并不是数字“0”或字符“…

Avalonia笔记2 -数据集合类控件

学习笔记&#xff1a; 1. DataGrid 笔记1中已经记录&#xff1b; 2. ItemsControl 属性&#xff1a; ItemsSource&#xff1a;数据源 ItemsControl.ItemTemplate&#xff1a;单项数据模板&#xff0c;内部使用<DataTemplate> 示例&#xff1a; <ItemsContr…

学习使用xbox手柄控制小乌龟节点移动

使用xbox手柄控制小乌龟&#xff0c;首先要下载joy功能包&#xff0c;发布sensor_msgs话题也就是手柄和ros通信的话题。 下载的步骤就根据官方文档即可 joy/Tutorials/ConfiguringALinuxJoystick - ROS Wiki 这里我提供一下具体步骤 第一步 安装joy 首先安装对应系统版本的…

第十四届蓝桥杯(C/C++ 大学B组)

试题 A&#xff1a;日期统计 #include <bits/stdc.h> using namespace std;const int numbers[100] {5, 6, 8, 6, 9, 1, 6, 1, 2, 4, 9, 1, 9, 8, 2, 3, 6, 4, 7, 7, 5, 9, 5, 0, 3, 8, 7, 5, 8, 1, 5,8, 6, 1, 8, 3, 0, 3, 7, 9, 2, 7, 0, 5, 8, 8, 5, 7, 0, 9, 9, 1, …

全局UI方法-弹窗一警告弹窗(AlertDialog)

1、描述 显示警告弹窗组件&#xff0c;可设置文本内容与响应回调。 2、属性 名称参数类型参数描述showAlertDialogParamWithConfirm | AlertDialogParamWithButtons定义并显示AlertDialog组件。 2.1、AlertDialogParamWithConfirm对象说明&#xff1a; 参数名称参数类型必填…

已注册的商标别忘了续展,新注可能难下证!

近期普推知产老杨遇到好几个网友和看过多个案例&#xff0c;以前商标名称可以申请注册下来&#xff0c;但是换字体注册不下来了&#xff0c;有的是不想续展想直接换字体申请注册&#xff0c;但是也没有下来。 这些商标名称主要是存在禁止注册或缺显&#xff0c;比如“柳林”以前…

对下载软件/文件进行校验的工具(Checksum and GPG)

前言 之前装软件一直都没有验证安装文件的习惯&#xff0c;信息安全意识不高&#xff0c;碰巧最近没啥事&#xff0c;微微写篇文章记录下校验工具&#xff08;互联网http、https、ftp 服务并没有那么安全&#xff0c;是可以被劫持篡改。老装软件选手了&#xff0c;是该养成个校…
最新文章