目录
最近在重读《Redis设计与实现》这本书,通过记录笔记,整理知识体系,希望我的笔记分享,能对致力于不断学习的你有点用。
1. 命令请求的执行过程概述
2.1 发送命令请求
2.2 读取命令请求
2.3命令执行(1)查找命令
2.3命令执行(2)预备操作,一系列检查和验证
2.3命令执行(3) 调用命令函数执行
2.3命令执行(4) 执行后续操作
2.4 将命令回复发送给客户端
总结
最近在重读《Redis设计与实现》这本书,通过记录笔记,整理知识体系,希望我的笔记分享,能对致力于不断学习的你有点用。
1. 命令请求的执行过程概述
一个命令请求从发送到获得回复的过程中,客户端和服务器需要完成一系列操作。举个
例子,如果我们使用客户端执行以下命令:
redis> SET KEY VALOE
OK
那么从客户端发送 SET KEY VALUE 命令到获得回复OK 期间,客户端和服务器共需要
执行以下4步操作:
1)客户端向服务器发送命令请求 SET KEY VALUE。
2)服务器接收并处理客户端发来的命令请求 SET KEY VALUE,在数据库中进行设置
操作,并产生命令回复OK。
3)服务器将命令回复 OK 发送给客户端。
4)客户端接收服务器返回的命令回复OK,并将这个回复打印给用户观看。
2.1 发送命令请求
Redis 服务器的命令请求来自 Redis 客户端,当用户在客户端中键入一个命令请求时,
客户端会将这个命令请求转换成协议格式,然后通过连接到服务器的套接字,将协议格式的
命令请求发送给服务器,
如图14-1所示

2.2 读取命令请求
当客户端与服务器之间的连接套接字因为客户端的写人而变得可读时,服务器将调用命
令请求处理器来执行以下操作:
1)读取套接字中协议格式的命令请求,并将其保存到客户端状态的输人缓冲区里面。
2)对输人缓冲区中的命令请求进行分析,提取出命令请求中包含的命令参数,参数的个数,然后分别将参数和参数个数保存到客户端状态的argv属性和argc属性里面。
3) 调用命令执行器,执行客户端指定的命令。
继续用上一个小节的 SET命令为例子,图14-2展示了程序将命令请求保存到客户端状
态的输人缓冲区之后,客户端状态的样子。

图 14-2 客户端状态中的命令请求
解析命令后格式

2.3命令执行(1)查找命令
命令执行器 要做的第一件事就是根据客户端状态的 argv[0]参数,在命令表(command
table)中查找参数所指定的命令,并将找到的命令保存到客户端状态的cmd 属性里面。
命令表是一个字典,字典的键是一个个命令名字,比如“set"、"get"、"de1"等
等;而字典的值则是一个个 redisCommand 结构,每个 rediscommand 结构记录了一个
Redis 命令的实现信息,表14-1记录了这个结构的各个主要属性的类型和作用。



2.3命令执行(2)预备操作,一系列检查和验证
- 检查客户端状态的cmd指针是否指向 NULL,如果是的话,那么说明用户输人的
命令名字找不到相应的命令实现,服务器不再执行后续步骤,并向客户端返回一个
错误。
- 根据客户端 cmd 属性指向的 redisCommand 结构的 arity属性,检查命令请求
所给定的参数个数是否正确,当参数个数不正确时,不再执行后续步骤,直接向客
户端返回一个错误。比如说,如果 redisCommand结构的arity属性的值为-3,
那么用户输人的命令参数个数必须大于等于3个才行。
- 检查客户端是否已经通过了身份验证,未通过身份验证的客户端只能执行 AUTH 命
令,如果未通过身份验证的客户端试图执行除AUTH命令之外的其他命令,那么服
务器将向客户端返回一个错误。
- 如果服务器打开了 maxmemory功能,那么在执行命令之前,先检查服务器的内存
占用情况,并在有需要时进行内存回收,从而使得接下来的命令可以顺利执行
2.3命令执行(3) 调用命令函数执行
在前面的操作中,服务器已经将要执行命令的实现保存到了客户端状态的cmd属性里
面,并将命令的参数和参数个数分别保存到了客户端状态的 argv 属性和 argv 属性里面,
当服务器决定要执行命令时,它只要执行以下语句就可以了:
// client 是指向客户端状态的指针
client->cmd->proc (client);
因为执行命令所需的实际参数都已经保存到客户端状态的 argv 属性里面了,所以命令
的实现函数只需要一个指向客户端状态的指针作为参数即可。
2.3命令执行(4) 执行后续操作
在执行完实现函数之后,服务器还需要执行一些后续工作:
- 如果服务器开启了慢查询日志功能,那么慢查询日志模块会检查是否需要为刚刚执
行完的命令请求添加一条新的慢查询日志。
- 根据刚刚执行命令所耗费的时长,更新被执行命令的rediscomand结构的
mi1liseconds 属性,并将命令的redisCommand结构的cal1s 计数器的值增一。
- 如果服务器开启了 AOF 持久化功能,那么 AOF 持久化模块会将刚刚执行的命令请
求写人到 AOF缓冲区里面。
- 如果有其他从服务器正在复制当前这个服务器,那么服务器会将刚刚执行的命令传
播给所有从服务器。
当以上操作都执行完了之后,服务器对于当前命令的执行到此就告一段落了,之后服务
器就可以继续从文件事件处理器中取出并处理下一个命令请求了。
2.4 将命令回复发送给客户端
前面说过,命令实现函数会将命令回复保存到客户端的输出缓冲区里面,并为客户端的
套接字关联命令回复处理器,当客户端套接字变为可写状态时,服务器就会执行命令回复处
理器,将保存在客户端输出缓冲区中的命令回复发送给客户端。
当命令回复发送完毕之后,回复处理器会清空客户端状态的输出缓冲区,为处理下一个
命令请求做好准备。
以图14-7所示的客户端状态为例子,当客户端的套接字变为可写状态时,命令回复处
理器会将协议格式的命令回复“+OK\r\n"发送给客户端。

继续以之前的 SET命令为例子,当客户端接到服务器发来的“+OK\z\n"协议回复时,
它会将这个回复转换成"OK\n",然后打印给用户看:
redis> SET KEY VALUE
OK
总结
以上就是 Redis 客户端和服务器执行命令请求的整个过程了
如果觉得对你有帮助,请点赞收藏和关注,我会持续更新的!
