设为首页 加入收藏

TOP

Redis源码整体运行流程详解(四)
2014-11-24 00:37:24 来源: 作者: 【 】 浏览:17
Tags:Redis 源码 整体 运行 流程 详解
el,fd,AE_READABLE, readQueryFromClient, c) == AE_ERR) { close(fd); zfree(c); return NULL; } } selectDb(c,0);//默认选择第0个db, db.c c->fd = fd;//文件描述符 c->name = NULL; c->bufpos = 0;//将指令结果发送给客户端的字符串长度 c->querybuf = sdsempty();//请求字符串初始化 c->querybuf_peak = 0;//请求字符串顶峰时的长度值 c->reqtype = 0;//请求类型 c->argc = 0;//参数个数 c->argv = NULL;//参数内容 c->cmd = c->lastcmd = NULL;//操作指令 c->multibulklen = 0;//块个数 c->bulklen = -1;//每个块的长度 c->sentlen = 0; c->flags = 0;//客户类型的标记,比较重要 c->ctime = c->lastinteraction = server.unixtime; c->authenticated = 0; c->replstate = REDIS_REPL_NONE; c->reploff = 0; c->repl_ack_off = 0; c->repl_ack_time = 0; c->slave_listening_port = 0; c->reply = listCreate();//存放服务器应答的数据 c->reply_bytes = 0; c->obuf_soft_limit_reached_time = 0; listSetFreeMethod(c->reply,decrRefCountVoid); listSetDupMethod(c->reply,dupClientReplyValue); c->bpop.keys = dictCreate(&setDictType,NULL);//下面三个参数在list数据阻塞操作时使用 c->bpop.timeout = 0; c->bpop.target = NULL; c->io_keys = listCreate(); c->watched_keys = listCreate();//事务命令CAS中使用 listSetFreeMethod(c->io_keys,decrRefCountVoid); c->pubsub_channels = dictCreate(&setDictType,NULL); c->pubsub_patterns = listCreate(); listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid); listSetMatchMethod(c->pubsub_patterns,listMatchObjects); // 如果不是伪客户端,那么将客户端加入到服务器客户端列表中 if (fd != -1) listAddNodeTail(server.clients,c);//添加到server的clients链表 initClientMultiState(c);//初始化事务指令状态 return c; }
客户端的请求指令字符串始终存放在querybuf中,在对querybuf解析后,将指令参数的个数存放在argc中,具体的指令参数存放在argv中;但是服务器应答的结果有两种存储方式:buf字符串、reply列表。

readQueryFromClient函数

readQueryFromClient函数用来读取客户端的请求命令行数据,并调用processInputBuffer函数依照redis通讯协议对数据进行解析。服务器使用最原始的read函数来读取客户端发送来的请求命令,并将字符串存储在querybuf中,根据需要对querybuf进行扩展。

void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
    redisClient *c = (redisClient*) privdata;
    int nread, readlen;
    size_t qblen;
    REDIS_NOTUSED(el);
    REDIS_NOTUSED(mask);

    server.current_client = c;
    readlen = REDIS_IOBUF_LEN; //1024 * 16
    /* If this is a multi bulk request, and we are processing a bulk reply
     * that is large enough, try to maximize the probability that the query
     * buffer contains exactly the SDS string representing the object, even
     * at the risk of requiring more read(2) calls. This way the function
     * processMultiBulkBuffer() can avoid copying buffers to create the
     * Redis Object representing the argument. */
    if (c->reqtype == REDIS_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1
        && c->bulklen >= REDIS_MBULK_BIG_ARG)
    {
        int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf);

        if (remaining < readlen) readlen = remaining;
    }

    qblen = sdslen(c->querybuf);
    if (c->querybuf_peak < qblen) c->querybuf_peak = qblen;
    //对querybuf的空间进行扩展
    c->querybuf = sdsMakeRoomFor(c->querybuf, readlen);
    //读取客户端发来的操作指令
    nread = read(fd, c->querybuf+qblen, readlen);
    if (nread == -1) {
        if (errno == EAGAIN) {
            nread = 0;
        } else {
            redisLog(REDIS_VERBOSE, "Reading from client: %s",strerror(errno));
            freeClient(c);
            return;
        }
    } else if (nread == 0) {
        redisLog(REDIS_VERBOSE, "Client closed connection");
        freeClient(c);
        return;
    }
    if (nread) {
        //改变querybuf的实际长度和空闲长度,len += nread, free -= nread;
        sdsIncrLen(c->querybuf,nread);
        c->lastinteraction = server.unixtime;
        if (c
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 4/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇 面试-数据库性能(索引) 下一篇存储方式与介质对性能的影响

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: