|
刚开始接触redis的时候为了了解redis的执行流程,粗略的翻了一下redis的源码然后画了一个草图。下面三张图分别代表了redis从开始启动到接收一个命令,再到把命令结果返回到客户端的过程,代码的执行顺序为每张图的从上到下从左到右。
图一:
当redis启动的时候,从程序的入口处redis.c/main()方法开始执行,首先进行初始化工作,先绑定一个时间事件,然后为这个时间绑定serverCron()方法.serverCron方法会每100毫秒执行一次,主要负责一些维护工作,比如drop过期的键等。紧接着就是要去监听一个端口,比如默认的6379。然后就走到初始化工作的末尾,为刚才监听的socket注册一个AE_READABLE事件,并为该事件绑定一个acceptTcpHandler方法,从名字上可以看出,该方法用于接收客户端的socket。
初始化工作完成之后就是要接收socket了,在aeMain方法中循环去调用aeProcessEvents方法,该方法每次都去IO多路复用器中获取已经就绪是事件,然后根据事件的类型对其进行分离,并执行相应的方法(fe->rfileProc或fe->wfileProc)。如果是第一次执行,因为在初始化的时候注册了一个fe->rfileProc=acceptTcpHandler,所以这里就会执行acceptTcpHandler这个方法。最后执行时间事件。
到此,redis就算启动完成了,然后就是通过循环去处理就绪的事件以及每个事件对应的方法。
图二:
从这张图可以看到acceptTcpHandler方法首先会创建一个客户端socket,然后为该socket注册AE_READBLE事件并绑定readQueryFromClient方法,这个方法用来解析并执行我们请求的命令,如set foo value等。注意这时候并没有执行,只是注册了一个事件,一单客户端的socket可读了,在aeMain方法下次循环时会通过图一中的aeApiPoll体现出来,最后才会通过fe->rfileProc去执行命令请求。
接下来图三说明了readQueryFromClient都做了什么事。
图三:
readQueryFromClient方法首先将命令读到每个客户端(socket)的缓冲区,然后通过一系列命令校验,最终通过call去执行命令并执行addReply方法,这个方法要做的事情就是为该客户端注册AE_WRITABLE事件并绑定sendReplyToClient方法,然后将要恢复的结果放入到该客户端的缓冲区。最后等该客户端可以写数据的时候,将结果发送给客户端。
这些事情做完之后接着就处理aof和从节点的问题,如果aof是开着的就调用feedAppendOnlyFile方法,该方法负责将命令放入到缓存中,最后有flushAppendOnlyFile将缓存写入到aof中,serverCron方法负责定期的调用flushAppendOnlyFile方法。最后如果有从节点的话就调用replicationFeedSlaves方法,该方法和上面的call方法一样会执行addReply方法,然后为所有的从节点注册相应的事件和方法,最终将命令发送给所有的从节点。
需要注意的是所有这些动作都是通过事件驱动的。 |
|
|