相关资料

redis.c
networking.c

1. 建立连接

/* Create an event handler for accepting new connections in TCP and Unix
 * domain sockets. */
for (j = 0; j < server.ipfd_count; j++) {
    if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,
        acceptTcpHandler,NULL) == AE_ERR)
        {
            redisPanic(
                "Unrecoverable error creating server.ipfd file event.");
        }
}
if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,
    acceptUnixHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.sofd file event.");
当客户端请求连接时,对应的事件处理函数是:acceptTcpHandler、acceptUnixHandler,其中:
acceptTcpHandler 接受 tcp 连接请求;
acceptUnixHandler 接受 unix 域连接请求。
void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
    int cport, cfd, max = MAX_ACCEPTS_PER_CALL;
    char cip[REDIS_IP_STR_LEN];
    REDIS_NOTUSED(el);
    REDIS_NOTUSED(mask);
    REDIS_NOTUSED(privdata);

    while(max--) {
        cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);
        if (cfd == ANET_ERR) {
            if (errno != EWOULDBLOCK)
                redisLog(REDIS_WARNING,
                    "Accepting client connection: %s", server.neterr);
            return;
        }
        redisLog(REDIS_VERBOSE,"Accepted %s:%d", cip, cport);
        acceptCommonHandler(cfd,0);
    }
}
anetTcpAccept 接受 tcp 连接,同时返回连接套接字cfd。
acceptCommonHandler 对连接套接字cfd及对应的客户端结构进行初始化。
c = createClient(fd))

初始化主要在 createClient 函数中进行,其中,通过注册事件处理函数 readQueryFromClient 来读取请求。

aeCreateFileEvent(server.el,fd,AE_READABLE,readQueryFromClient, c)

2. 请求处理

请求处理可以分为3个步骤:
1. 读取请求
2. 解析请求
3. 执行请求
readQueryFromClient 函数是请求处理的起点,该函数将请求读取到 c->querybuf 中,然后调用 processInputBuffer 函数。
void processInputBuffer(redisClient *c) {
    /* Keep processing while there is something in the input buffer */
    while(sdslen(c->querybuf)) {
        /* Immediately abort if the client is in the middle of something. */
        if (c->flags & REDIS_BLOCKED) return;

        /* REDIS_CLOSE_AFTER_REPLY closes the connection once the reply is
         * written to the client. Make sure to not let the reply grow after
         * this flag has been set (i.e. don't process more commands). */
        if (c->flags & REDIS_CLOSE_AFTER_REPLY) return;

        /* Determine request type when unknown. */
        if (!c->reqtype) {
            if (c->querybuf[0] == '*') {
                c->reqtype = REDIS_REQ_MULTIBULK;
            } else {
                c->reqtype = REDIS_REQ_INLINE;
            }
        }

        if (c->reqtype == REDIS_REQ_INLINE) {
            if (processInlineBuffer(c) != REDIS_OK) break;
        } else if (c->reqtype == REDIS_REQ_MULTIBULK) {
            if (processMultibulkBuffer(c) != REDIS_OK) break;
        } else {
            redisPanic("Unknown request type");
        }

        /* Multibulk processing could see a <= 0 length. */
        if (c->argc == 0) {
            resetClient(c);
        } else {
            /* Only reset the client when the command was executed. */
            if (processCommand(c) == REDIS_OK)
                resetClient(c);
        }
    }
}
if (c->reqtype == REDIS_REQ_INLINE) {
    if (processInlineBuffer(c) != REDIS_OK) break;
} else if (c->reqtype == REDIS_REQ_MULTIBULK) {
    if (processMultibulkBuffer(c) != REDIS_OK) break;
}

根据请求类型,分别调用 processInlineBuffer 和 processMultibulkBuffer 解析请求。
最后调用 processCommand 函数执行请求。

c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr);
根据argv[0],查找CommandTable,找到对应的执行函数。

call(c,REDIS_CALL_FULL);
调用函数执行命令。

标签: none

已有 8 条评论

  1. 看的我热血沸腾啊

  2. 哈哈哈,写的太好了https://www.cscnn.com/

  3. 《街角少年第四季》欧美综艺高清在线免费观看:https://www.jgz518.com/xingkong/36667.html

  4. 《吉米霍法之死》记录片高清在线免费观看:https://www.jgz518.com/xingkong/60147.html

  5. 博主太厉害了!

  6. 《戴帽子的猫》喜剧片高清在线免费观看:https://www.jgz518.com/xingkong/34719.html

  7. 《包豪斯时代》欧美剧高清在线免费观看:https://www.jgz518.com/xingkong/149560.html

  8. 《罗丹2017》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/165441.html

添加新评论