Redis 是如何执行的?

news2024/10/7 18:25:14

文章目录

  • 命令执行流程
    • 步骤一:用户输入一条命令
    • 步骤二:客户端先将命令转换成 Redis 协议,然后再通过 socket 连接发送给服务器端
    • 步骤三:服务器端接收到命令
    • 步骤四:执行前准备
    • 步骤五:执行最终命令,调用 redisCommand 中的 proc 函数执行命令。
    • 步骤六:执行完后相关记录和统计
    • 步骤七:返回结果给客户端
  • 扩展知识:I/O 多路复用
  • 小结

Redis 是如何执行的?收到的答案往往是:客户端发命令给服务器端,服务端收到执行之后再返回给客户端。

然而对于执行细节却「避而不谈」 ,当继续追问服务器端是如何执行的?能回答上来的人更是寥寥无几,这未免让人有些遗憾,一个我们每天都在用的技术,知道原理的人却寥若晨星。

对于任何一门技术,如果你只停留在「会用」的阶段,那就很难有所成就。

命令执行流程

一条命令的执行过程有很多细节,但大体可分为:

  • 客户端先将用户输入的命令,转化为 Redis 相关的通讯协议
  • 再用 socket 连接的方式将内容发送给服务器端,服务器端在接收到相关内容之后,
  • 先将内容转化为具体的执行命令,再判断用户授权信息和其他相关信息,当验证通过之后会执行最终命令
  • 命令执行完之后,会进行相关的信息记录和数据统计
  • 然后再把执行结果发送给客户端,这样一条命令的执行流程就结束了
  • 如果是集群模式的话,主节点还会将命令同步至子节点

在这里插入图片描述

步骤一:用户输入一条命令

步骤二:客户端先将命令转换成 Redis 协议,然后再通过 socket 连接发送给服务器端

客户端和服务器端是基于 socket 通信的,服务器端在初始化时会创建了一个 socket 监听,用于监测链接客户端的 socket 链接,源码如下:

void initServer(void) {
    //......
    // 开启 Socket 事件监听
    if (server.port != 0 &&
        listenToPort(server.port,server.ipfd,&server.ipfd_count) == C_ERR)
        exit(1);
    //......
}

socket 小知识:每个 socket 被创建后,会分配两个缓冲区,输入缓冲区和输出缓冲区。 写入函数并不会立即向网络中传输数据,而是先将数据写入缓冲区中,再由 TCP 协议将数据从缓冲区发送到目标机器。一旦将数据写入到缓冲区,函数就可以成功返回,不管它们有没有到达目标机器,也不管它们何时被发送到网络,这些都是 TCP 协议负责的事情。 注意:数据有可能刚被写入缓冲区就发送到网络,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,这取决于当时的网络情况、当前线程是否空闲等诸多因素,不由程序员控制。 读取函数也是如此,它也是从输入缓冲区中读取数据,而不是直接从网络中读取。

当 socket 成功连接之后,客户端会先把命令转换成 Redis 通讯协议(RESP 协议,REdis Serialization Protocol)发送给服务器端,这个通信协议是为了保障服务器能最快速的理解命令的含义而制定的,如果没有这个通讯协议,那么 Redis 服务器端要遍历所有的空格以确认此条命令的含义,这样会加大服务器的运算量,而直接发送通讯协议,相当于把服务器端的解析工作交给了每一个客户端,这样会很大程度的提高 Redis 的运行速度。例如,当我们输入 set key val 命令时,客户端会把这个命令转换为 *3\r\n$3\r\nSET\r\n$4\r\nKEY\r\n$4\r\nVAL\r\n 协议发送给服务器端。 更多通讯协议,可访问官方文档:https://redis.io/topics/protocol

步骤三:服务器端接收到命令

服务器会先去输入缓冲中读取数据,然后判断数据的大小是否超过了系统设置的值(默认是 1GB),如果大于此值就会返回错误信息,并关闭客户端连接。 默认大小如下图所示:

在这里插入图片描述
当数据大小验证通过之后,服务器端会对输入缓冲区中的请求命令进行分析,提取命令请求中包含的命令参数,存储在 client 对象(服务器端会为每个链接创建一个 Client 对象)的属性中。

步骤四:执行前准备

  1. 判断是否为退出命令,如果是则直接返回;

  2. 非 null 判断,检查 client 对象是否为 null,如果是返回错误信息;

  3. 获取执行命令,根据 client 对象存储的属性信息去 redisCommand 结构中查询执行命令;

  4. 用户权限效验,未通过身份验证的客户端只能执行 AUTH(授权) 命令,未通过身份验证的客户端执行了 AUTH 之外的命令则返回错误信息;

  5. 集群相关操作,如果是集群模式,把命令重定向到目标节点,如果是 master(主节点) 则不需要重定向;

  6. 检查服务器端最大内存限制,如果服务器端开启了最大内存限制,会先检查内存大小,如果内存超过了最大值会对内存进行回收操作;

  7. 持久化检测,检查服务器是否开启了持久化和持久化出错停止写入配置,如果开启了此配置并且有持久化失败的情况,禁止执行写命令;

  8. 集群模式最少从节点(slave)验证,如果是集群模式并且配置了 replminslavestowrite(最小从节点写入),当从节点的数量少于配置项时,禁止执行写命令;

  9. 只读从节点验证,当此服务器为只读从节点时,只接受 master 的写命令;

  10. 客户端订阅判断,当客户端正在订阅频道时,只会执行部分命令(只会执行 SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE,其他命令都会被拒绝)。

  11. 从节点状态效验,当服务器为 slave 并且没有连接 master 时,只会执行状态查询相关的命令,如 info 等;

  12. 服务器初始化效验,当服务器正在启动时,只会执行 loading 标志的命令,其他的命令都会被拒绝;

  13. lua 脚本阻塞效验,当服务器因为执行 lua 脚本阻塞时,只会执行部分命令;

  14. 事务命令效验,如果执行的是事务命令,则开启事务把命令放入等待队列;

  15. 监视器 (monitor) 判断,如果服务器打开了监视器功能,那么服务器也会把执行命令和相关参数发送给监视器 (监视器是用于监控服务器运行状态的)。

当服务器经过以上操作之后,就可以执行真正的操作命令了

步骤五:执行最终命令,调用 redisCommand 中的 proc 函数执行命令。

步骤六:执行完后相关记录和统计

  1. 检查慢查询是否开启,如果开启会记录慢查询日志;
  2. 检查统计信息是否开启,如果开启会记录一些统计信息,例如执行命令所耗费时长和计数器(calls)加1;
  3. 检查持久化功能是否开启,如果开启则会记录持久化信息; ④ 如果有其它从服务器正在复制当前服务器,则会将刚刚执行的命令传播给其他从服务器。

步骤七:返回结果给客户端

命令执行完之后,服务器会通过 socket 的方式把执行结果发送给客户端,客户端再把结果展示给用户,至此一条命令的执行就结束了。

扩展知识:I/O 多路复用

Redis 使用的是 I/O 多路复用功能来监听多 socket链接的,这样就可以使用一个线程链接来处理多个请求,减少线程切换带来的开销,同时也避免了 I/O 阻塞操作,从而大大提高了 Redis 的运行效率。

在这里插入图片描述
综合来说,此步骤的执行流程如下:

  • 与服务器端以 socket 和 I/O 多路复用的技术建立链接;
  • 将命令转换为 Redis 通讯协议,再将这些协议发送至缓冲区。

小结

当用户输入一条命令之后,客户端会以 socket 的方式把数据转换成 Redis 协议,并发送至服务器端,服务器端在接受到数据之后,会先将协议转换为真正的执行命令,在经过各种验证以保证命令能够正确并安全的执行,但验证处理完之后,会调用具体的方法执行此条命令,执行完成之后会进行相关的统计和记录,然后再把执行结果返回给客户端,整个执行流程,如下图所示:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML5+CSS3+JS小实例:网站实现一键切换暗色主题

实例:网站实现一键切换暗色主题 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge&…

V-rep(CoppeliaSim)添加相机,与python联合仿真,并使用python读取V-rep中的RGB图与深度图

目录 前言在V-rep中构建场景建立python与V-rep通信 前言 本文主要介绍了如何使用python与V-rep联合仿真&#xff0c;并用OpenCV可视化V-rep中视觉传感器所能看到的 RGB图和深度图&#xff0c;效果图如下。 在V-rep中构建场景 本文使用的V-rep版本是3.5&#xff1a; 打开V-…

深度学习在语义分割中的进展与应用

埃弗顿戈梅德&#xff08;Everton Gomede&#xff09; 一、说明 语义分割是计算机视觉领域的一项关键任务&#xff0c;涉及将图像中的每个像素分类为预定义的类。这项任务在从自动驾驶汽车到医学成像的各种应用中都具有深远的影响。深度学习的出现显著提高了语义分割模型的功能…

小型企业成为网络犯罪分子获取数据的目标

在过去十年的大部分时间里&#xff0c;网络犯罪的巨额资金来自针对大型组织的勒索软件攻击。这种威胁仍然存在。但犯罪分子可能会将注意力转向中小企业 (SMB)。这对消费者的影响将是巨大的。 将软件即服务 (SaaS) 技术用于核心业务功能继续将中小企业整合到全球供应链中。由于…

kubeSphere集群部署nacos

kubeSphere部署nacos 个人环境说明执行nacos数据脚本kubeSphere添加配置创建有状态副本集修改集群配置文件 创建外部访问服务访问 个人环境说明 由于我之前这个项目就是dockerjenkins部署的,只是现在升级到k8skubeSphere所有下面有些操作我可能不同,例如我的nacos配置文件就是d…

论文阅读:Blind Super-Resolution Kernel Estimation using an Internal-GAN

这是发表在 2019 年 NIPS 上的一篇文章&#xff0c;那个时候还叫 NIPS&#xff0c;现在已经改名为 NeurIPS 了。文章中的其中一个作者 Michal Irani 是以色 Weizmann Institute of Science (魏茨曼科学研究学院) 的一名教授&#xff0c;对图像纹理的内在统计规律有着很深入的研…

UG NX二次开发(C#)-Ufun和NXOpen混合编程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、Ufun函数3、 NXOpen4、混合编程实现1、前言 在UG NX二次开发过程中,采用Ufun功能比较简单,能用比较少的代码实现我们需要的功能,但是ufun函数的功能不是很强大,尤其随着UG NX的版本…

中央集成式架构量产时代,openVOC方案将引发软件开发模式变革

2024年&#xff0c;中央计算区域控制架构正式进入规模化量产周期&#xff0c;汽车智能化正式迈入2.0时代&#xff0c;产业生态、应用创新、开发模式都将迎来巨大变革。 同时&#xff0c;随着ChatGPT引发的AIGC领域的爆发式增长&#xff0c;人工智能技术掀起全球万亿级信息化应…

开箱即用的企业级数据和业务管理中后台前端框架Ant Design Pro 5的开箱使用和偏好配置

Ant Design Pro 介绍 Ant Design Pro 是一个开箱即用的企业级前端解决方案&#xff0c;基于 Ant Design 设计体系&#xff0c;提供了丰富的组件和功能&#xff0c;帮助开发者更快速地开发和部署企业级应用。 Ant Design Pro 使用 React、umi 和 dva 这三个主要的前端开发技术…

天翼云云间高速实现租户跨地域内网互通

一、业务需求 用户业务在襄阳、武汉两个云池部署&#xff0c;希望通过云间高速产品将两个资源池云内资源通过云内专网实现内网互通。要求内网双向互通。 二、测试环境配置 云池vpc名称vpc网段子网内网ip/gweip主机名互联网带宽襄阳ceshi192.168.0.0/16192.168.1.0/24192.168.…

基于element ui封装table组件

效果图&#xff1a; 1.封装表格代码如下 <template> <div><div class"TableList"><el-tablev-loading"loading"selection-change"selectionChange"class"table":data"tableData":border"hasBorde…

阿里云数据库PolarDB费用价格_MySQL版_PolarDB_分布式版

阿里云数据库PolarDB租用价格表&#xff0c;云数据库PolarDB MySQL版2核4GB&#xff08;通用&#xff09;、2个节点、60 GB存储空间55元5天&#xff0c;云数据库 PolarDB 分布式版标准版2核16G&#xff08;通用&#xff09;57.6元3天&#xff0c;阿里云百科aliyunbaike.com分享…

OpenCV-Python(21):OpenCV中的轮廓性质

3.轮廓的性质 本文我们将主要学习基于轮廓来提取一些经常使用的对象特征。 3.1 长宽比 边界矩形的宽高比&#xff1a; x,y,w,h cv2.boundingRect(cnt) aspect_ratio float(w)/h 3.2 Extent 轮廓面积与边界矩形面积的比。 area cv2.contourArea(cnt) x,y,w,h cv2.bounding…

EXPLORING DIFFUSION MODELS FOR UNSUPERVISED VIDEO ANOMALY DETECTION 论文阅读

EXPLORING DIFFUSION MODELS FOR UNSUPERVISED VIDEO ANOMALY DETECTION 论文阅读 ABSTRACT1. INTRODUCTION2. RELATEDWORK3. METHOD4. EXPERIMENTAL ANALYSIS AND RESULTS4.1. Comparisons with State-Of-The-Art (SOTA)4.2. Diffusion Model Analysis4.3. Qualitative Result…

Apache Commons JCS缓存解决方案

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff01;今天&#xff0c;咱们来聊聊Apache Commons JCS&#xff0c;一个Java界里的缓存大杀器。缓存技术&#xff0c;对于提高应用性能来说&#xff0c;就像是给它加了一剂兴奋剂&#xff0c;能让数据访问变得快如闪电。…

Idea如何从磁盘中应用 下载好的插件流程,安装zip压缩包。

1、将下载的插件文件&#xff08;通常是一个ZIP文件&#xff09;复制到IntelliJ IDEA的“plugins”文件夹中。 IDEA版本 2、重启IntelliJ IDEA。 3、在设置窗口中&#xff0c;选择左侧的“Plugins”。 4、选择之前复制到“plugins”文件夹中的插件文件&#xff0c;点击“OK”按…

Android---Kotlin 学习013

互操作性和可空性 Java 世界里所有对象都可能是 null&#xff0c;而 kotlin 里面不能随便给一个变量赋空值的。所有&#xff0c;kotlin 取调用 java 的代码就很容易出现返回一个 null&#xff0c;而 Kotlin 的接收对象不能为空&#xff0c;你不能想当然地认为 java 的返回值就…

[卷积神经网络]FCOS--仅使用卷积的Anchor Free目标检测

项目源码&#xff1a; FCOShttps://github.com/tianzhi0549/FCOS/ 一、概述 作为一种Anchor Free的目标检测网络&#xff0c;FCOS并不依赖锚框&#xff0c;这点类似于YOLOx和CenterNet&#xff0c;但CenterNet的思路是寻找目标的中心点&#xff0c;而FCOS则是寻找每个像素点&…

边缘计算网关:在智慧储能系统中做好储能通信管家

背景 目前储能系统主要由储能单元和监控与调度管理单元组成&#xff0c;储能单元包含储能电池组(BA)、电池管理系统(BMS)、储能变流器(PCS)等&#xff1b;监控与调度管理单元包括中央控制系统(MGCC)、能量管理系统(EMS)等。 2021年8月&#xff0c;国家发改委发布《电化学储能…

Unreal Engine游戏引擎的优势

在现在这个繁荣的游戏开发行业中&#xff0c;选择合适的游戏引擎是非常重要的。其中&#xff0c;Unreal Engine作为一款功能强大的游戏引擎&#xff0c;在业界广受赞誉。那Unreal Engine游戏引擎究竟有哪些优势&#xff0c;带大家简单的了解一下。 图形渲染技术 Unreal Engin…