百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

向Redis发出一条命令,会发生什么?

yuyutoo 2025-03-13 21:50 10 浏览 0 评论

天下皆知美之为美,斯恶已;皆知善之为善,斯不善已。
故有无相生,难易相成,长短相形,高下相倾,音声相和,前后相随,恒也。
是以圣人处无为之事,行不言之教。万物作焉而不辞,生而不有,为而不恃,功成而弗居。夫唯弗居,是以不去。

文章导航

日常工作中,我们经常在Redis中设置值和取值,那么一条命令发出去之后,都经历了什么呢?

127.0.0.1:6379> SET key value
OK

一条命令,从发送到得到回复的过程,客户端和服务端需要完成一系列的操作。以上面代码为例,客户端和服务端共需要经历下面的步骤:

  1. 客户端向服务端发送SET key value命令。
  2. 服务端接收客户端请求,并处理。在数据库中进行设置操作,并产生命令回复OK。
  3. 服务端将命令回复OK发送给客户端
  4. 客户端接收服务端返回命令并回复OK,并将该回复显示给用户

本文关于Redis 源码部分,源于Redis 7.0

客户端发送命令请求

将用户在客户端输入一个命令后,客户端会将命令请求转成协议格式,并发送给服务端。

客户端向服务端发送命令

比如在客户端输入下面命令:

127.0.0.1:6379> SET key value
OK

客户端会将该命令转成协议格式,并发送给服务端。

*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n

为了使文章结构清晰,关于协议格式不再赘述,文末详细介绍!

服务端读取命令请求

当客户端向服务端发送完命令请求后,服务端会调用命令请求处理器进行下面操作:

  1. 读取协议格式的命令请求,并保存到客户端缓冲区(Client )。
  2. 对命令请求解析,提取出命令参数及参数个数。
  3. 调用命令执行器,执行命令。

redis-server client.drawio.png

上图是Redis将命令请求保存到客户端缓冲区后的结构。

client是客户端缓冲区结构体,其中将协议格式的命令请求保存在client的querybuf中。argc保存命令请求的个数。参数保存到argv中。后文我们用client来替代客户端缓冲区

接下来Redis Server会调用命令执行器完成执行命令的后续部分。

命令执行器之查找命令

首先命令执行器要根据客户端缓冲区的argv[0]在redisCommandTable中查找参数指定的命令,并保存到client的cmd字段中。

redisCommandTable是一个全局变量,定义了所有 Redis 命令,值为redisCommand结构,包括命令的名称、实现函数、所需参数数量以及其他属性。它用于存储和管理 Redis 的命令信息。

以下是redisCommand结构体的主要字段整理出来,完整描述详见源码server.h/redisCommand

字段名

类型

描述

declared_name

char*

命令的声明名称

summary

char*

命令的摘要

complexity

char*

复杂度描述

since

char*

命令引入的版本号

proc

redisCommandProc*

命令实现函数指针

arity

int

参数数量

flags

uint64_t

命令标志

acl_categories

uint64_t

ACL分类

getkeys_proc

redisGetKeysProc*

获取键参数的函数指针

microseconds

long long

命令执行时间(微秒)

calls

long long

命令调用次数

rejected_calls

long long

被拒绝的命令调用次数

failed_calls

long long

失败的命令调用次数

redisCommandTable采用与大小写无关的查找策略,因此命令名字的大小写不影响查找。

命令执行器之预执行

现在我们已经准备好执行命令了,但是在执行前还需要一些预备检查,以便命令可以正确、顺利的执行。

  1. 客户端身份验证:如果Redis服务器启用了身份验证机制,首先会验证客户端是否已成功通过身份验证。只有通过身份验证的客户端才能继续执行后续的命令。
  2. 命令权限检查:根据ACL(访问控制列表)配置,检查当前连接的客户端是否具有执行该命令的权限。ACL可以限制每个用户或用户组能够执行的特定命令。
  3. 命令存在性检查:检查客户端请求的命令是否存在于Redis服务器的命令字典中。如果命令不存在,则向客户端返回错误响应。
  4. 参数数量检查:根据命令定义的参数数量要求(arity字段),检查客户端请求的参数数量是否满足要求。如果参数数量不正确,则向客户端返回错误响应。
  5. 参数格式检查:对于某些命令,进一步检查参数的格式是否符合预期。例如,对于SET命令,会检查键和值参数的类型是否正确。
  6. 服务器状态检查:在执行某些命令之前,可能会检查服务器的状态是否允许执行该命令。例如,在主从复制模式下,只有主节点允许执行写操作。

命令执行器之执行

到这一步,所有的前置准备工作已经就绪,接下来要真正执行了!

前面我们知道客户端缓冲区保存了命令的参数和参数个数,分别保存在client的argv、argc属性中,当执行命令的时候,运行下面语句即,代码位于service.c/call

c->cmd->proc(c); //setCommand(client)

client结构

被调用的命令实现函数执行响应的操作,并产生对应的命令回复,保存在客户端缓冲区(client的reply和buf属性中)。

命令回复结构

命令执行器之善后

命令执行结束后,命令执行器还需要执行一些善后工作:

  1. 释放资源:在命令执行完毕后,命令执行器需要释放相关的资源,包括临时数据结构、数据库锁等。这样可以避免资源泄露和浪费,保持系统的稳定性和高效性。
  2. 日志记录:根据配置和需求,命令执行器可能需要记录命令执行的日志。这包括成功执行的命令、出现错误的命令、重要事件等。日志记录有助于故障排查、性能优化和监控。
  3. 统计和计数:命令执行器可能需要对命令执行过程中的统计数据进行更新和计数。例如,命令调用次数、执行时间、失败次数等。这些统计信息可以用于性能分析和监控系统健康状态。
  4. 处理事务回滚:如果命令执行过程中发生了错误,导致事务无法完成,命令执行器可能需要执行相应的回滚操作,撤销之前已执行的命令。这保证了事务的一致性和可靠性。

将命令回复发送给客户端,并打印

Redis Server 执行命令回复处理器,将客户端缓冲区中的命令回复发送给客户端。

客户端在收到命令回复后,将协议格式转换为人类可读模式,并打印出来。

到这里,客户端和服务端的整个请求过程已经结束了。有同学开始问了,集群下是如何运行的?客户端怎么知道key所在节点的呢?

在集群模式下,服务端在接收到命令请求后,会先根据key判断命令请求中的key所在槽是否在当前节点,如果不是,会向客户端返回一个MOVED错误,客户端根据MOVED错误信息转向正确的节点重新发送命令请求并执行上述操作。

redis cluster check

Redis协议格式

Redis 协议是一种用于与 Redis 数据库进行通信的简单而高效的文本协议。它使用 TCP/IP 进行传输,并以行为单位进行交互。

在 Redis 协议中,每个请求和响应都由多个字符组成。我们可以将协议的格式分为请求格式和响应格式:

请求格式:

  • *<参数数量> CR LF:表示参数数量的前缀,用于指定请求中的参数个数。
  • $<参数长度> CR LF:表示参数长度的前缀,用于指定接下来的参数的长度。如果参数为空,则长度为 -1。
  • <参数值> CR LF:参数的实际内容。

举个例子,如果我们要设置一个键值对,请求可以如下所示:

*3 // 参数数量为 3

$3 // 第一个参数长度为 3

SET // 第一个参数值为 SET

$5 // 第二个参数长度为 5

mykey // 第二个参数值为 mykey

$7 // 第三个参数长度为 7

myvalue // 第三个参数值为 myvalue

响应格式:

Redis 的响应也由多个字符组成,有以下几种可能的类型:

  • 状态回复(Status Reply):以 "+" 开头,后面跟着状态信息。
  • 错误回复(Error Reply):以 "-" 开头,后面跟着错误信息。
  • 整数回复(Integer Reply):以 ":" 开头,后面跟着一个整数。
  • 批量回复(Bulk Reply):以 "$" 开头,后面跟着回复的长度和内容。如果长度为 -1,则表示空值。
  • 多条批量回复(Multi Bulk Reply):以 "*" 开头,后面跟着回复的数量和内容。

举个例子,如果我们要获取一个键的值,响应可以如下所示:


$7 // 响应内容的长度为 7

myvalue // 响应内容为 myvalue

完整的协议格式参考:
https://redis.io/docs/reference/protocol-spec/

相关推荐

《保卫萝卜2》安卓版大更新 壕礼助阵世界杯

《保卫萝卜2:极地冒险》本周不仅迎来了安卓版本的重大更新,同时将于7月4日本周五,带来“保卫萝卜2”安卓版本世界杯主题活动的火热开启,游戏更新与活动两不误。一定有玩家会问,激萌塔防到底进行了哪些更新?...

儿童手工折纸:胡萝卜,和孩子一起边玩边学carrot

1、准备两张正方形纸,一橙一绿,对折出折痕。2、橙色沿其中一条对角线如图折两三角形。3、把上面三角折平,如图。4、绿色纸折成三角形。5、再折成更小的三角形。6、再折三分之一如图。7、打开折纸,压平中间...

《饥荒》食物代码有哪些(饥荒最新版代码总汇食物篇)

饥荒游戏中,玩家们需要获取各种素材与食物,进行生存。玩家们在游戏中,进入游戏后按“~”键调出控制台使用代码,可以直接获得素材。比如胡萝卜的代码是carrot,玉米的代码是corn,南瓜的代码是pump...

Skyscanner:帮你找到最便宜机票 订票不求人

你喜欢旅行吗?在合适的时间、合适的目的地,来一场说走就走的旅行?机票就是关键!Skyscanner这款免费的手机应用,在几秒钟内比较全球600多家航空公司的航班安排、价格和时刻表,帮你节省金钱和时间。...

小猪佩奇第二季50(小猪佩奇第二季英文版免费观看)

Sleepover过夜Itisnighttime.现在是晚上。...

我在民政局工作的那些事儿(二)(我在民政局上班)

时间到了1997年的秋天,经过一年多的学习和实践,我在处理结婚和离婚的事情更加的娴熟,也获得了领导的器重,所以我在处理平时的工作时也能得心应手。这一天我正在离婚处和同事闲聊,因为离婚处几天也遇不到人,...

夏天来了就你还没瘦?教你不节食13天瘦10斤的哥本哈根减肥法……

好看的人都关注江苏气象啦夏天很快就要来了你是否和苏苏一样身上的肉肉还没做好准备?真是一个悲伤的故事……下面这个哥本哈根减肥法苏苏的同事亲测有效不节食不运动不反弹大家快来一起试试看吧~DAY1...

Pursuing global modernization for peaceful development, mutually beneficial cooperation, prosperity for all

AlocalworkeroperatesequipmentintheChina-EgyptTEDASuezEconomicandTradeCooperationZonei...

Centuries-old tea road regains glory as Belt and Road cooperation deepens

FUZHOU/ST.PETERSBURG,Oct.2(Xinhua)--NestledinthepicturesqueWuyiMountainsinsoutheastChi...

15 THE NUTCRACKERS OF NUTCRACKER LODGE (CONTINUED)胡桃夹子小屋里的胡桃夹子(续篇)

...

AI模型部署:Triton Inference Server模型部署框架简介和快速实践

关键词:...

Ftrace function graph简介(flat function)

引言由于android开发的需要与systrace的普及,现在大家在进行性能与功耗分析时候,经常会用到systrace跟pefetto.而systrace就是基于内核的eventtracing来实...

JAVA历史版本(java各版本)

JAVA发展1.1996年1月23日JDK1.0Java虚拟机SunClassicVM,Applet,AWT2.1997年2月19日JDK1.1JAR文件格式,JDBC,JavaBea...

java 进化史1(java的进阶之路)

java从1996年1月第一个版本诞生,到2022年3月最新的java18,已经经历了27年,整整18个大的版本。很久之前有人就说java要被淘汰,但是java活到现在依然坚挺,不知道java还能活...

学习java第二天(java学完后能做什么)

#java知识#...

取消回复欢迎 发表评论: