图解redis服务器(1)

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 图解redis服务器(1),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

目录

1.引言

2.命令请求的执行的过程

3.发送命令请求

4.读取命令请求

 5.命令执行器(查找命令实现)

6.执行预备操作

7.调用命令函数

 8.执行后续操作

9.返回客户端and 打印命令回复


1.引言

Redis服务器负责与多个客户端建立网络连接,处理客户端发送的 命令请求,在数据库中保存客户端执行命令所产生的数据,并通过资源 管理来维持服务器自身的运转

以服务器执行SET命令的过程作为例子,展示服务 器处理命令请求的整个过程,说明在执行命令的过程中,服务器和客户 端进行了什么交互,服务器中的各个不同组件又是如何协作的

2.命令请求的执行的过程

set key value

那么从客户端发送SET KEY VALUE命令到获得回复OK期间,客户端和服务器共需要执行以下操作:

1)客户端向服务器发送命令请求SET KEY VALUE。

2)服务器接收并处理客户端发来的命令请求SET KEY VALUE, 在数据库中进行设置操作,并产生命令回复OK。

3)服务器将命令回复OK发送给客户端。

4)客户端接收服务器返回的命令回复OK,并将这个回复打印给用 户观看。 本节接下来的内容将对这些操作的执行细节进行补充,详细地说明 客户端和服务器在执行命令请求时所做的各种工作

3.发送命令请求

Redis服务器的命令请求来自Redis客户端,当用户在客户端中键入 一个命令请求时,客户端会将这个命令请求转换成协议格式,然后通过 连接到服务器的套接字,将协议格式的命令请求发送给服务器(协议 即是AOF文件格式)

图解redis服务器(1)

 set key value

格式

*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALUE\r\n

4.读取命令请求

当客户端与服务器之间的连接套接字因为客户端的写入而变得可读 时,服务器将调用命令请求处理器来执行以下操作

1)读取套接字中协议格式的命令请求,并将其保存到客户端状态 的输入缓冲区里面。

2)对输入缓冲区中的命令请求进行分析,提取出命令请求中包含 的命令参数,以及命令参数的个数,然后分别将参数和参数个数保存到 客户端状态的argv属性和argc属性里面。

3)调用命令执行器,执行客户端指定的命令

图解:继续用的SET命令为例子

图解redis服务器(1)

 图解:将分析结果保存在客户端的ARGV和argc

图解redis服务器(1)

 5.命令执行器(查找命令实现)

命令执行器要做的第一件事就是根据客户端状态的argv[0]参数,在 命令表(command table)中查找参数所指定的命令,并将找到的命令保 存到客户端状态的cmd属性里面。

命令表是一个字典,字典的键是一个个命令名字,比 如”set”、”get”、”del”等等;而字典的值则是一个个redisCommand结构, 每个redisCommand结构记录了一个Redis命令的实现信息

关于command的结构

图解redis服务器(1)

 有关标识

图解redis服务器(1)

6.执行预备操作

到目前为止,服务器已经将执行命令所需的命令实现函数(保存 客户端状态的cmd属性)、参数(保存在客户端状态的argv属性)、参 数个数(保存在客户端状态的argc属性)都收集齐了,但是在真正执行 命令之前,程序还需要进行一些预备操作,从而确保命令可以正确、顺 利地被执行,这些操作包括

检查客户端状态的cmd指针是否指向NULL,如果是的话,那么说明用户输入的命令名字找不到相应的命令实现,服务器不再执行后续步骤,并向客户端返回一个错误。

·根据客户端cmd属性指向的redisCommand结构的arity属性,检查命令请求所给定的参数个数是否正确,当参数个数不正确时,不再执行后 续步骤,直接向客户端返回一个错误。比如说,如果redisCommand结构 的arity属性的值为-3,那么用户输入的命令参数个数必须大于等于3个才 行。

·检查客户端是否已经通过了身份验证,未通过身份验证的客户端 只能执行AUTH命令,如果未通过身份验证的客户端试图执行除AUTH 命令之外的其他命令,那么服务器将向客户端返回一个错误。

·如果服务器打开了maxmemory功能,那么在执行命令之前,先检 查服务器的内存占用情况,并在有需要时进行内存回收,从而使得接下 来的命令可以顺利执行。如果内存回收失败,那么不再执行后续步骤, 向客户端返回一个错误。

·如果服务器上一次执行BGSAVE命令时出错,并且服务器打开了 stop-writes-on-bgsave-error功能,而且服务器即将要执行的命令是一个写 命令,那么服务器将拒绝执行这个命令,并向客户端返回一个错误。

·如果客户端当前正在用SUBSCRIBE命令订阅频道,或者正在用 PSUBSCRIBE命令订阅模式,那么服务器只会执行客户端发来的 SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE四个 命令,其他命令都会被服务器拒绝。

·如果服务器正在进行数据载入,那么客户端发送的命令必须带有l 标识(比如INFO、SHUTDOWN、PUBLISH等等)才会被服务器执 行,其他命令都会被服务器拒绝。

·如果服务器因为执行Lua脚本而超时并进入阻塞状态,那么服务器 只会执行客户端发来的SHUTDOWN nosave命令和SCRIPT KILL命令, 其他命令都会被服务器拒绝。

·如果客户端正在执行事务,那么服务器只会执行客户端发来的 EXEC、DISCARD、MULTI、WATCH四个命令,其他命令都会被放进 事务队列中。

·如果服务器打开了监视器功能,那么服务器会将要执行的命令和 参数等信息发送给监视器。当完成了以上预备操作之后,服务器就可以 开始真正执行命令了

7.调用命令函数

在前面的操作中,服务器已经将要执行命令的实现保存到了客户端 状态的cmd属性里面,并将命令的参数和参数个数分别保存到了客户端 状态的argv属性和argv属性里面,当服务器决定要执行命令时,它只要 执行以下语句就可以了

// client
是指向客户端状态的指针
client->cmd->proc(client);

等同于setcommand(client)

因为执行命令所需的实际参数都已经保存到客户端状态的argv属性 里面了,所以命令的实现函数只需要一个指向客户端状态的指针作为参 数即可

下图展现展示了客户端包含了命令实 现、参数和参数个数的样子

图解redis服务器(1)

 被调用的命令实现函数会执行指定的操作,并产生相应的命令回 复,这些回复会被保存在客户端状态的输出缓冲区里面(buf属性和 reply属性),之后实现函数还会为客户端的套接字关联命令回复处理 器,这个处理器负责将命令回复返回给客户端

下图展现一个:对于前面SET命令的例子来说,函数调用setCommand(client)将 产生一个”+OK\r\n”回复,这个回复会被保存到客户端状态的buf属性里 面

图解redis服务器(1)

 8.执行后续操作

在执行完实现函数之后,服务器还需要执行一些后续工作:

·如果服务器开启了慢查询日志功能,那么慢查询日志模块会检查 是否需要为刚刚执行完的命令请求添加一条新的慢查询日志。

·根据刚刚执行命令所耗费的时长,更新被执行命令的 redisCommand结构的milliseconds属性,并将命令的redisCommand结构 的calls计数器的值增一。

·如果服务器开启了AOF持久化功能,那么AOF持久化模块会将刚 刚执行的命令请求写入到AOF缓冲区里面。

·如果有其他从服务器正在复制当前这个服务器,那么服务器会将 刚刚执行的命令传播给所有从服务器。 当以上操作都执行完了之后,服务器对于当前命令的执行到此就告 一段落了,之后服务器就可以继续从文件事件处理器中取出并处理下一 个命令请求

9.返回客户端and 打印命令回复

命令实现函数会将命令回复保存到客户端的输出缓冲区 里面,并为客户端的套接字关联命令回复处理器,当客户端套接字变为 可写状态时,服务器就会执行命令回复处理器,将保存在客户端输出缓 冲区中的命令回复发送给客户端

当命令回复发送完毕之后,回复处理器会清空客户端状态的输出缓 冲区,为处理下一个命令请求做好准备

当客户端接收到协议格式的命令回复之后,它会将这些回复转换成 人类可读的格式,并打印给用户观看

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/129583.html

(0)

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!