这个问题说简单也很简单,无非就是客户端发送命令请求,服务器读取命令请求,然后是命令执行器查找命令实现,执行预备操作,调用命令实现函数,执行后续工作。
但是我们想要了解的不能简简单单的就是这些。下面我们详细的来分析一下Redis命令执行的全过程。
发送命令请求
但用户通过客户端输入一个命令请求的时候,客户端首先会对用户输入的命令请求进行一个格式转换,转换成协议格式,然后通过连接到服务器的套接字把这个已经格式化的命令发送给服务器(服务器是通过套节字和客户端或者是其他服务器连接通信的)
读取命令请求
但客户端与服务器端的套接字因为客户端的写入而变的可读时(这点需要查阅Redis文件事件的内容,这里不再赘述),
服务器会首先读取套接字中的协议格式的命令请求,并将它保存到客户端状态的输入缓冲区中(这里输入缓冲区的大小可以根据输入内容动态的缩小或者扩大,但是最大不能超过1GB否则服务器将关闭这个客户端)
然后服务器对输入缓冲区中的命令请求进行分析,提取命令请求中包含的命令参数,以及参数的个数,然后分别将参数和参数个数保存到客户端状态的argv属性和argc属性中(argv属性是一个数组,数组中的每个项都是一个字符串对象,其中argv[0]是要执行的命令,之后的其他项是传给的命令参数,argc属性负责记录argv数组的长度)
最后是调用命令执行器,执行客户端指定的命令。
命令执行
当服务器分析得到argv和argc属性的值之后,服务器会根据arg[0]的值在命令表中查找所对应的命令实现函数,Redis命令表示一个字典(字典的又一个应用)key是命令的名字,value对应一个redisCommand结构,保存了命令的实现函数、命令的标志、命令应该指定的参数个数、命令总执行次数、总消耗时间等统计信息。
找到实现函数之后并不是真正的执行命令,还需要进行一些检查操作,
检查用户输入的命令名字是否能找到相应的命令实现,
然后检查用户输入的参数个数是否符合要求(redisCommand结构中有个arity属性,如果是 -3 表示输入的参数个数必须大于等于3)
然后还要检查客户端是否通过了身份验证,如果通过了身份验证客户端状态里的authenticated属性的值是1,否则是0(Auth命令)
还有就是内存占用情况、上次执行bgsave出错的话是否打开了stop-writes-on-bgsave-error等等检查。
检查全部通过之后就是调用命令的实现函数,也就是真正的执行命令了,执行完之后会将执行的结果保存客户端状态的输出缓冲区中,输出缓冲区有两个,一个是固定大小16Kb,用来保存长度较小的回复,还有就是可变大小的输出缓冲区,用来保存长度较大的回复【注意:服务器通过两种模式限制客户端输出缓冲区的大小,一种是硬性限制,一种是软性限制,如果超出的硬性限制的大小,服务器立即关闭客户端,如果超出的软性限制,但是没有超硬性限制,那么记录超出的时间,如果一直超出,持续时间超过了设置的时间,那么关闭客户端,相反不会关闭】
最后执行后续的工作,包括更新慢查询日志记录,更新redisCommand结构中的一些统计信息,还有一些持久化操作,复制操作等。
最后的最后就是将结果发送给客户端,仍旧是套接字。
版权声明:本文为博主原创文章,未经博主允许不得转载。