redis源码初探

开始学习redis的源码了,记录一下过程。首先下载了redis的第一个发布版本0.091版本:
https://download.redis.io/rel...

在redis.c文件里找到了redis服务启动的入口,即main函数。粗略看一眼启动过程:

首先是main函数:

int main(int argc, char **argv) {
    ...
    aeMain(server.el);
    ...
}

进入aeMain函数,它在ae.c文件中:

void aeMain(aeEventLoop *eventLoop){
    eventLoop->stop = 0;
    while (!eventLoop->stop)
        aeProcessEvents(eventLoop, AE_ALL_EVENTS);
}

进入aeProcessEvents函数:

int aeProcessEvents(aeEventLoop *eventLoop, int flags){
    ...
    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服务程序启动的时候就添加了一个事件:

int main(int argc, char **argv) {
    ...
    if (aeCreateFileEvent(server.el, server.fd, AE_READABLE,
        acceptHandler, NULL, NULL) == AE_ERR) oom("creating file event");
    ...
}

其中server.fd在服务初始化的时候赋值了,就是一个server socket,这里是监听它是否可读,当可读的时候调用acceptHandler来处理server socket可读事件。

看看acceptHandler函数:

static void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
    ...
    cfd = anetAccept(server.neterr, fd, cip, &cport);
    ...
    if (createClient(cfd) == NULL) {
        ...
    }
    ...
}

在接受了客户端的请求后,调用了createClient函数:

static redisClient *createClient(int fd) {
    ...
    if (aeCreateFileEvent(server.el, c->fd, AE_READABLE,
        readQueryFromClient, c, NULL) == AE_ERR) {
        ...
    }
    ...
}

可以看到这里又添加了一个事件,与客户端连接的socket有数据可读时,调用readQueryFromClient函数:

static void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
    ...
    processCommand(c);
    ...
}

这个函数就是执行客户端传过来的各种指令,到这里,差不多把redis的源码大体上过了一遍了,下面看一个addReply函数,很容易可以看出,它是通过添加和处理socket可写事件,来返回信息给客户端。

static void addReply(redisClient *c, robj *obj) {
    if (listLength(c->reply) == 0 &&
        aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,
        sendReplyToClient, c, NULL) == AE_ERR) return;
    if (!listAddNodeTail(c->reply,obj)) oom("listAddNodeTail");
    incrRefCount(obj);
}

今天的源码先分析到这里,之后再看redis是具体如何处理各个指令的,0.091版本的redis支持49条指令,比最新版本少很多,很适合用来入门。

你可能感兴趣的:(redis后端java源码)