当前位置: 首页 > 后端技术 > Java

Redis源码初探

时间:2023-04-01 14:24:10 Java

开始学习redis源码,记录过程。首先下载redis的第一个release版本0.091:https://download.redis.io/rel...在redis.c文件中找到了redis服务启动的入口,即main函数。快速浏览一下启动过程:首先是主要功能:intmain(intargc,char**argv){...aeMain(server.el);...}输入aeMain函数,它在ae.c文件中:voidaeMain(aeEventLoop*eventLoop){eventLoop->stop=0;while(!eventLoop->stop)aeProcessEvents(eventLoop,AE_ALL_EVENTS);}输入aeProcessEvents函数:intaeProcessEvents(aeEventLoop*eventLoop,intflags){...retval=select(maxfd+1,&rfds,&wfds,&efds,tvp);...fe->fileProc(eventLoop,fe->fd,fe->clientData,mask);...retval=te->timeProc(eventLoop,id,te->clientData);...}截取上面三段代码,你大概可以看出redis的启动逻辑和事件处理模型。它使用select阻塞并等待感兴趣的事件到达,然后处理该事件并完成处理然后它阻塞并等待下一个事件发生,依此类推。所以简单的看一下,在事件集合中添加和删除事件就可以让redis工作了。回头看main函数,发现在redis服务程序启动的时候加了一个事件:intmain(intargc,char**argv){...if(aeCreateFileEvent(server.el,server.fd,AE_READABLE,acceptHandler,NULL,NULL)==AE_ERR)oom("创建文件事件");...}其中server.fd是在服务初始化的时候赋值的,它是一个serversocket,这里是监听是否可读,当可读时调用acceptHandler处理serversocket可读事件。查看acceptHandler函数:staticvoidacceptHandler(aeEventLoop*el,intfd,void*privdata,intmask){...cfd=anetAccept(server.neterr,fd,cip,&cport);...if(createClient(cfd)==NULL){...}...}接受客户端请求后,调用createClient函数:staticredisClient*createClient(intfd){...if(aeCreateFileEvent(server.el,c->fd,AE_READABLE,readQueryFromClient,c,NULL)==AE_ERR){...}...}可以看到这里又增加了一个事件。当客户端连接的socket有数据需要读取时,调用readQueryFromClient函数:staticvoidreadQueryFromClient(aeEventLoop*el,intfd,void*privdata,intmask){...processCommand(c);...}这个函数是执行客户端的各种指令。到这里,几乎redis的源码我都大致看了一遍。让我们看看下面的addReply函数。不难看出,它通过添加和处理socket可写事件向客户端返回信息。staticvoidaddReply(redisClient*c,robj*obj){if(listLength(c->reply)==0&&aeCreateFileEvent(server.el,c->fd,AE_WRITABLE,sendReplyToClient,c,NULL)==AE_ERR)返回;如果(!listAddNodeTail(c->reply,obj))oom("listAddNodeTail");incrRefCount(obj);}今天的源码先分析到这里,再看看redis是如何处理每条指令的,0.091版本Redis支持49条指令,比最新版本少了很多,非常适合入门。