前文我们了解了 Redis 的启动过程。在initServer()函数中创建了一些循环事件来监听TCP端口和Unix的Sockets,从而使Redis服务器可以接收新的连接。今天我们再一起来看一下Redis究竟是如何处理命令并返回结果的。
处理新连接
Redis在initServer()函数中创建循环事件调用了acceptTcpHandler和acceptUnixHandler函数(都在networking.c文件中)来处理接收到的TCP连接和Unix的Sockets连接。这两个函数又调用了acceptCommonHandler()函数,在这个函数中调用了createClient()函数创建一个新的client对象,用来表示一个新的客户端连接。
createClient()函数具体做了哪些事情呢?
首先为变量c分配了内存,接着将Socket连接置为非阻塞状态,并且设置了TCP无延迟。然后创建了File循环事件(aeCreateFileEvent)来调用readQueryFromClient函数。新建的客户端默认连接的是服务器的第一个数据库(编码为0),最后需要设置好客户端的各种属性和状态。
读一个客户端的命令
刚刚我们提到了readQueryFromClient函数,从名称上就能看出来这个函数是用来从客户端读取命令的。下面来看看函数的具体实现。
Redis会先将命令读入缓冲区,一次最多读取的大小是PROTO_IOBUF_LEN(1024*16)bit。然后调用processInputBufferAndReplicate()函数,来处理缓冲区中的数据,如果客户端是master(主从同步过程),那么Redis会计算处理前后缓冲区的不同部分,以确定从节点接收了多少数据。processInputBufferAndReplicate()函数会处理客户端向服务器发送命令和主节点向从节点发送命令这两种情况,不过最后都需要调用processInputBuffer()函数。
processInputBuffer()函数会先判断客户端是否正常,如果出现连接中断或者客户端阻塞等情况,就会立即停止处理命令,不做无用功。然后根据读取的请求生成相应的Redis可以执行的命令(包括参数)。不同的请求类型分别调用processInlineBuffer()和processMultibulkBuffer()函数。生成好命令之后,交给processCommand()(server.c文件中)函数执行,如果返回C_OK则重置客户端,等待下一个命令。如果返回的是C_ERR,则客户端会被销毁(比如执行QUIT命令)。
processCommand()函数会从Redis启动时加载的命令表中查找命令,然后检查命令的执行权限。
如果是cluster,这时会判断key是否属于当前的master,不属于需要返回重定向信息。
如果内存不够用,这里也需要判断一下是否有可以释放的内存,如果没有,就不能执行命令,返回错误信息。
接下来会判断一些不能接收写命令的情况:
-
服务器不能进行持久化
-
作为master,没有足够的可用的slave
-
此服务器为只读的slave,只有它的master可以接收写命令
在订阅模式中,只能接收指定的命令:(P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT。
当slave和master失联时,只能接收有flag "t"的命令,例如,INFO,SLAVEOF等。
如果命令没有CMD_LOADING标志,并且当前服务器正在加载数据,则不能接收此命令。
对 lua 脚本的长度进行限制。
进行完上面的各种条件判断之后,才可以真正开始调用call()函数执行命令。
执行命令并返回
call()函数的参数是client类型的,取出cmd成员进行执行。
1/* Call the command. */ 2dirty = server.dirty; 3start = ustime(); 4c->cmd->proc(c); 5duration = ustime()-start; 6dirty = server.dirty-dirty; 7if (dirty < 0) dirty = 0;
如果是写命令,就会使服务器变“脏”,也就是服务器需要标记一下内存中的某些页有了改变。这对于Redis的持久化来说非常重要,它可以知道这个命令影响了多少个key。命令执行完之后并没有结束,call函数还会做一些其他操作。例如记录日志,写AOF文件,向从节点同步命令等。
至于返回值,每个命令有各自的处理方法,我们后面在介绍。
到这里,Redis处理命令的过程也就完成了。
后面我们会再通过具体的命令来对这个过程做一个更清晰的介绍。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 走近源码:神奇的 HyperLogLog
- 走近源码:Redis 的启动过程
- 走近源码:Redis跳跃列表究竟怎么跳
- 走近源码:Redis命令执行过程(客户端)
- 走近源码:Redis 命令执行过程(客户端)
- 走近监控系统的神经中枢
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
亿级流量网站架构核心技术
张开涛 / 电子工业出版社 / 2017-4 / 99
《亿级流量网站架构核心技术》一书总结并梳理了亿级流量网站高可用和高并发原则,通过实例详细介绍了如何落地这些原则。本书分为四部分:概述、高可用原则、高并发原则、案例实战。从负载均衡、限流、降级、隔离、超时与重试、回滚机制、压测与预案、缓存、池化、异步化、扩容、队列等多方面详细介绍了亿级流量网站的架构核心技术,让读者看后能快速运用到实践项目中。 不管是软件开发人员,还是运维人员,通过阅读《亿级流......一起来看看 《亿级流量网站架构核心技术》 这本书的介绍吧!