Redis 是如何执行的?

在以往的面试中,当问到一些面试者:Redis 是如何执行的?收到的答案往往是:客户端发命令给服务器端,服务端收到执行之后再返回给客户端。然而对于执行细节却「避而不谈」 ,当继续追问服务器端是如何执行的?能回答上来的人更是寥寥无几,这未免让人有些遗憾,一个我们每天都在用的技术,知道原理的人却寥若晨星。

对于任何一门技术,如果你只停留在「会用」的阶段,那就很难有所成就,甚至还有被裁员和找不到工作的风险,我相信能看此篇文章的你,一定是积极上进想有所作为的人,那么借此机会,我们来深入的解一下 Redis 的执行细节。

命令执行流程

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

image.png

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

步骤二:客户端先将命令转换成 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

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

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

I/O 多路复用机制如下图所示: IO多路复用.png 综合来说,此步骤的执行流程如下:

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

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

服务器会先去输入缓冲中读取数据,然后判断数据的大小是否超过了系统设置的值(默认是 1GB),如果大于此值就会返回错误信息,并关闭客户端连接。 默认大小如下图所示: redis-run-max_query_buffer.png 当数据大小验证通过之后,服务器端会对输入缓冲区中的请求命令进行分析,提取命令请求中包含的命令参数,存储在 client 对象(服务器端会为每个链接创建一个 Client 对象)的属性中。

步骤四:执行前准备

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

小结

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

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

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

相关文章

第五章I/O管理

I/O章节5.1.1I/O分类(1)按使用特性分(2)I/O设备按传输速率分类(3)I/O设备按信息交换的单位分5.1.2I/O控制器5.1.3I/O控制方式(1)程序直接控制方式(轮询)&…

列表使用与内部实现原理

列表类型 (List) 是一个使用链表结构存储的有序结构,它的元素插入会按照先后顺序存储到链表结构中,因此它的元素操作 (插入\删除) 时间复杂度为 O(1),所以相对来说速度还是比较快的,但它的查询时间复杂度为 O(n),因此查询可能会比较慢。 1 基础使用 列表类型的使用相对来…

操作系统习题

操作系统习题习题一一、选择习题二一、选择二、综合题习题三一、选择题?二、简答题进程互斥遵循的四个原则:空闲让进、忙则等待、有限等待、让权等待重点习题四一、选择??二、综合题死锁产生的 4 个必要条件是: &#…

WCF trace、log

1. 打开wcf配置: 2. enable trace , log 可以改变log路径: 3. 用 SvcTraceViewer.exe (直接在c盘下搜索) 查看 4. 如果想自定义trace: catch(Exception ex) { Trace.Writ…

字典使用与内部实现原理

字典类型 (Hash) 又被成为散列类型或者是哈希表类型,它是将一个键值 (key) 和一个特殊的“哈希表”关联起来,这个“哈希表”表包含两列数据:字段和值。例如我们使用字典类型来存储一篇文章的详情信息,存储结构如下图所示: 同理我们也可以使用字典类型来存储用户信息,并且…

算法设计与分析复习第一二章(时间复杂度和蛮力法)

算法复习一二章第一章时间复杂度第二章蛮力法(1)查找问题顺序查找(2)排序问题选择排序起泡排序(3)组合问题0-1bag问题概述(略)(4)图问题哈密顿回路TSP问题&am…

有序集合使用与内部实现原理

有序集合类型 (Sorted Set) 相比于集合类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序值。有序集合的存储元素值也是不能重复的,但分值是可以重复的。 当我们把学生的成绩存储在有序集…

Android 友盟SDK 终极解决报错:SocialSDK_QQZone_2.jar contains native libraries that

转自:http://bbs.umeng.com/thread-6552-1-2.html 报错信息:The library SocialSDK_QQZone_2.jar contains native libraries that will not run on the device.解决方案:此问题和Eclipse环境有关,按照如下步骤操作即可Eclipse-&g…

Redis 持久化——AOF

使用 RDB 持久化有一个风险,它可能会造成最新数据丢失的风险。因为 RDB 的持久化有一定的时间间隔,在这个时间段内如果 Redis 服务意外终止的话,就会造成最新的数据全部丢失。 可能会操作 Redis 服务意外终止的条件: 安装 Redis 的机器停止运行,蓝屏或者系统崩溃;安装 R…

第四章文件管理

第四章文件管理4.1_2初识文件4.1_2文件的逻辑结构无结构文件有结构文件(1)顺序文件(2)索引文件索引顺序文件多级索引顺序文件4.1_3文件目录文件控制块FCB(2)单级目录(3)两级目录结构…

免费的管理页面模板

2019独角兽企业重金招聘Python工程师标准>>> Free Bootstrap Admin Templates for Designers 1. Admin Lite AdminLTE - 是一个完全响应式管理模板。基于Bootstrap3的框架。高度可定制的,易于使用。支持很多的屏幕分辨率适合从小型移动设备到大型台式机。…

Redis 持久化——RDB

Redis 的读写都是在内存中,所以它的性能较高,但在内存中的数据会随着服务器的重启而丢失,为了保证数据不丢失,我们需要将内存中的数据存储到磁盘,以便 Redis 重启时能够从磁盘中恢复原有的数据,而整个过程就叫做 Redis 持久化。 Redis 持久化也是 Redis 和 Memcached 的主…

MATLAB使用教程

MATLAB使用教程2.1.1 MATLAB系统环境(1)命令行窗口(2)工作区窗口2.2.1MATLAB数值数据(1)强制转换如转换为int整形(2)判断变量类型(3)复型(4&#…

解决myeclipse中新导入的工程旁出现红色感叹号的问题

2019独角兽企业重金招聘Python工程师标准>>> 或许很多像我这样的java初学者在使用myeclipse时出现新导入的工程旁边有红色的感叹号。 1.问题一般就是java build path 设置不正确的问题。解决步骤如下: 右击工程找到Build Path——>Configure Build Pa…

层次分析法

层次分析法一、层次分析法原理二、解题步骤(1)层次结构模型(2)成对比较矩阵①成对比较矩阵(有现成代码进行一致性检验和求权重)②成对比较阵标度表及举例③一致性检验三、旅游性问题举例(1&…

Redis 持久化——混合持久化

RDB 和 AOF 持久化各有利弊,RDB 可能会导致一定时间内的数据丢失,而 AOF 由于文件较大则会影响 Redis 的启动速度,为了能同时使用 RDB 和 AOF 各种的优点,Redis 4.0 之后新增了混合持久化的方式。 在开启混合持久化的情况下,AOF 重写时会把 Redis 的持久化数据,以 RDB 的…

多属性决策模型

多属性决策模型一、多属性决策模型(1)特点(2)属性值的归一化①效益型②成本型③固定型④偏离型⑤区间型⑥偏离区间型二、例题及步骤①建立数学模型②属性值归一化③对不同的属性构建成对比较矩阵并计算属性权重④计算每个公司的WA…

Redis 管道技术——Pipeline

管道技术(Pipeline)是客户端提供的一种批处理技术,用于一次处理多个 Redis 命令,从而提高整个交互的性能。 通常情况下 Redis 是单行执行的,客户端先向服务器发送请求,服务端接收并处理请求后再把结果返回给客户端,这种处理模式在非频繁请求时不会有任何问题。 但如果…

灰色预测

灰色预测一、灰色预测理论简介(1)灰色系统(2)灰色系统的特点(3)灰色生成(4)GM(1,1)模型(5)GM(1,1)模型精度检验…

Redis 过期策略与源码分析

在 Redis 中我们可以给一些元素设置过期时间,那当它过期之后 Redis 是如何处理这些过期键呢? 过期键执行流程 Redis 之所以能知道那些键值过期,是因为在 Redis 中维护了一个字典,存储了所有设置了过期时间的键值,我们称之为过期字典。 过期键判断流程如下图所示: 过期…