这是我参与「第五届青训营 」伴学笔记创作活动的第 19 天
七、服务器
1、命令请求的执行过程
我们客户端发送命令到服务器回复我们OK的过程中,发生了以下操作。
1、客户端向服务器发送命令请求
2、服务器接收并处理客户端发来的命令请求,在数据库中执行相对应的操作
3、服务器将回复发送给客户端
4、客户端将收到的回复显示到界面
1.1:发送命令请求
发送命令请求是客户端把请求转成协议格式然后发送(在netty学习的时候接触过Redis的协议,自定义协议)
1.2:读取命令请求
读取请求当数据库忙碌的时候,多路复用会把我们的socket加入到队列里,当轮到我们的时候,就开始处理我们的命令
1.2.1、读取命令保存到客户端状态的输入缓冲区
1.2.2、命令解析,提取出命令的命令参数,以及命令参数的个数,然后将参数和参数个数分别保存到客户端状态的argv属性和argc属性。
1.2.3、调用命令执行器,执行客户端发送的命令。
1.3、命令执行器
1.3.1、查找命令实现
根据客户端状态的argv[0]参数来获取命令参数,然后在命令表里查询这个参数所指定的命令。
命令表的key是命令的名字,比如set,get
命令表的value是一个个redisCommand结构,每个redisCommand结构记录一个Redis命令的实现信息。其中包括了该命令调用的函数以及各种辅助参数,比如服务器总共执行了多少次这个命令,还有sflags属性,是表达这个命令的所属,比如,写入W,读入R,管理命令A,等等。
自己思考一下,字符串如何去操作redis的函数,就能想明白如何运行,难度不大。
1.3.2、执行预备操作
检查用户输入的命令是否指向null,指向null说明命令不存在
根据redisCommand的属性来判断输入的参数是否正确
检查客户端是否经过了身份验证,如果没有身份验证则只能执行auth命令
如果服务器打开了最大内存的功能,在执行命令之前,先检查服务器的内存占用情况,如果已经达到最大内存内开始内存回收,淘汰算法,如果内存回收失败则返回错误
如果服务器打开了监视器功能,那么服务器就会把将要执行的命令和参数发送给监视器
1.3.3、调用命令的实现函数
这里就是通过字符串来调用函数的实现
1.3.4、执行后续工作
如果服务器开启了慢查询日志功能,就要判断刚才执行的是否满足慢日志的要求
根据执行的时间来更新redisCommand的milliseconds属性,并且把calls计数器+1
如果服务器开启了AOF持久化功能,那么就要把命令写入到缓冲区
如果其他服务器正在复制当前服务器,那么服务器会把刚才执行的命令传播给所有从服务器
1.4、将回复发送给客户端
客户端打印命令回复也是将Redis的协议转换成我们能理解的字符串。
很重要的一个函数,时间事件。周期性时间函数,serverCron函数
2、serverCron函数
serverCron函数每100ms执行一次。
1、更新服务器缓存
2、更新LRU时钟
3、更新服务器每秒执行命令次数
4、更新服务器内存峰值记录
5、处理SIGTERM信号
6、管理客户端资源
7、管理数据库资源
8、执行被延迟的BGWRITEAOF
9、检查持久化操作的运行状态
10、将AOF缓冲区中的内容写入AOF文件
11、关闭异步客户端
12、增加cronloops计数器的值
3、初始化服务器
3.1、初始化服务器状态结构
3.2、载入配置选项
3.3、初始化服务器数据结构
3.4、还原数据库状态
3.5、执行事件循环