Redis设计与实现:第十四章 -服务器

参考:《Redis设计与实现》

1、命令请求执行过程

1、客户端发送命令请求

       当用户在客户端输入一个命令,客户端会将这个命令转换为协议格式,通过连接到服务端的套接字,将协议命令发送给服务端。

过程图示:
在这里插入图片描述
       

2、读取命令组装结构

读取命令操作主要分成下面两步:

  • 读取套接字中的格式请求,并将其保存到客户端状态的输入缓冲区里面。
  • 对输入缓冲区的命令进行分析,提取命令参数与个数信息保存到argv和argc属性中

比如说set key value这个命令,提取之后填充到客户端状态的参数中的数据结构如下所示:
在这里插入图片描述
       

3、查找命令执行对象(cmd)

       在命令表(command table)中查找参数指定的命令,命令表是一个字典,字典的键是命令的名字,字典的值就是redisCommand结构。

以下是redisCommand结构的主要属性:

	typedef struct redisCommand{
		char *name; //命令的名字
		
		redisCommandProc proc;//函数指针,指向命令的实现函数
		
		int arity ;//命令参数的个数,用于检查命令的请求格式是否正确
		
		char *sflags;//命令的属性,命令的存在值看后面的描述
	
		int flags;//对sflags标识进行分析得出的二进制标识,由程序自动生成

		long long calls; //服务器总共执行了多少次这个命令

		long long milliseconds;//服务器执行这个命令消耗的总时长
	}

       sflags标识的值,以及意义:
标识| 意义
       命令的大小写不影响命令表的查询结果。

       

4、检查校验操作

  • 检查客户端状态的cmd指针是否指向NULL,如果是的话说明用户输入的命令名字找不到相应的命令实现。则应该返回错误
  • 根据客户端状态的arity属性,检查命令给定的参数个数是否正确。参数不正确时直接返回错误
  • 检查客户端是否通过身份验证,没有通过身份验证返回错误
  • 如果服务器打开了maxmemory功能,在执行命令之前,检查内存占用情况,在需要的时候进行内存回收,回收失败返回错误
  • …(具体其他的检查操作查看原书描述)
           

5、执行命令

       在之前的操作中,服务器已经把执行命令保存到客户端状态中,所以执行命令操作其实只是通过指针进行一次函数调用即可。被调用的函数实现指定操作,并产生对应的命令回复,这些回复保存在客户端状态的输出(固定)缓冲区中。

       

6、后续操作

在执行完命令之后,服务器还会执行相应的后续操作,包括下面的操作:

  • 如果服务器开启了慢查询日志,那么慢查询日志模块会检查是否需要添加一条新的慢查询日志。
  • 更新milseconds和calls计数器
  • 如果开启了AOF持久化功能,持久化模块会将刚刚执行的命令写入到AOF文件
  • 如果其他服务器正在复制当前服务器,服务器会将命令发送给其他服务器

7、客户端接收命令并打印

       客户端收到命令格式的回复消息,会将这些命令转换成可读格式打印在客户端。
       

2、ServerCron函数

       因为ServerCron函数执行的操作比较多,这边只记录我觉得稍微重要点的操作,其他的操作直接参考原书

1、管理客户端资源

ServerCron每次都会调用ClientCron函数,clientCron每次都会对一定数量的客户端进行检查:

  • 如果客户端和服务端连接已经超时,程序会释放这个客户端。
  • 如果客户端上一次请求,输入缓冲区超过一定长度,服务端会释放客户端当前输入缓冲区,并重新创建一个新的输入缓冲区,从而防止客户端的输入缓冲区消费过多的内存。
           

2、管理数据库资源

       ServerCron每次都会调用databaseCron函数,对一部分数据库进行检查,删除其中的过期键,按照需要对字典进行收缩操作。

       

3、初始化服务器

略,直接参考原文。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章