redis源码阅读(6)-timeEvent之异步处理客户端

clientCron函数针对client的操作主要由以下几点:
(1)如果客户端没有在阻塞调用状态,比如说BLPOP操作等,如果客户端上次请求server的时间与server端现在时间差超过server.maxidletime,直接关闭客户端,删除和此客户端相关的任何数据,表示此客户端已经被异常关闭,或者长时间没有进行操作。
(2)如果客户端处在阻塞请求状态,并且阻塞请求的超时时间已到,回复客户端已经超时,并且从阻塞key的hash表中删除此客户端,如果此客户端还调用了BRPOPLPUSH,那么需要清除此客户端的操作的key的目得key的指针。
(3)调整此客户端的querybuf,以节省内存。
(4) 设置此客户端的flag。并将此客户端放入到unblocked_clients中。

void clientsCron(void) {
    /* Make sure to process at least 1/(server.hz*10) of clients per call.
     * Since this function is called server.hz times per second we are sure that
     * in the worst case we process all the clients in 10 seconds.
     * In normal conditions (a reasonable number of clients) we process
     * all the clients in a shorter time. */
    int numclients = listLength(server.clients);
    int iterations = numclients/(server.hz*10);

    if (iterations < 50)
        iterations = (numclients < 50) ? numclients : 50;
    while(listLength(server.clients) && iterations--) {
        redisClient *c;
        listNode *head;

        /* Rotate the list, take the current head, process.
         * This way if the client must be removed from the list it's the
         * first element and we don't incur into O(N) computation. */
        listRotate(server.clients);
        head = listFirst(server.clients);
        c = listNodeValue(head);
        /* The following functions do different service checks on the client.
         * The protocol is that they return non-zero if the client was
         * terminated. */
        **//处理上面提到的(1)(3)(4)**
       if (clientsCronHandleTimeout(c)) continue;
         //**如果客户端没有满足(1)中条件,那么调整此客户端的querybuf,以节省内存。**
        if (clientsCronResizeQueryBuffer(c)) continue;
    }
}

执行(1)(2)情况:

/* Check for timeouts. Returns non-zero if the client was terminated */
int clientsCronHandleTimeout(redisClient *c) {
    time_t now = server.unixtime;

    if (server.maxidletime &&
        !(c->flags & REDIS_SLAVE) &&    /* no timeout for slaves */
        !(c->flags & REDIS_MASTER) &&   /* no timeout for masters */
        !(c->flags & REDIS_BLOCKED) &&  /* no timeout for BLPOP */
        dictSize(c->pubsub_channels) == 0 && /* no timeout for pubsub */
        listLength(c->pubsub_patterns) == 0 &&
        (now - c->lastinteraction > server.maxidletime))
    {
        //处理(1)情况
        redisLog(REDIS_VERBOSE,"Closing idle client");
        freeClient(c);
        return 1;
        //处理(2)情况
    } else if (c->flags & REDIS_BLOCKED) {
        if (c->bpop.timeout != 0 && c->bpop.timeout < now) {
            addReply(c,shared.nullmultibulk);
            unblockClientWaitingData(c);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值