@[TOC]

redis的monitor命令

功能

通过执行monitor命令,可将客户机更改为监视器。实时打印出 Redis 服务器接收到的命令,一般是在调试的时候使用这个命令

原理

monitor命令的原理是客户端的REDIS_MONITOR开启监视器标志,然后将客户端信息添加到服务器的监视器链接列表之中。服务器初始化replicationFeedMonitors迭代所有监控器,并将接管到的命令信息传送给所有监控器

这个方法的功能就是将参数列表中的参数发送给监控器

void replicationFeedMonitors(client *c, list *monitors, int dictid, robj **argv, int argc) {
    listNode *ln;
    listIter li;
    int j;
    sds cmdrepr = sdsnew("+");
    robj *cmdobj;
    struct timeval tv;

    gettimeofday(&tv,NULL);
    cmdrepr = sdscatprintf(cmdrepr,"%ld.%06ld ",(long)tv.tv_sec,(long)tv.tv_usec);

    if (c->flags & CLIENT_LUA) {
        cmdrepr = sdscatprintf(cmdrepr,"[%d lua] ",dictid);
    } else if (c->flags & CLIENT_UNIX_SOCKET) {
        cmdrepr = sdscatprintf(cmdrepr,"[%d unix:%s] ",dictid,server.unixsocket);
    } else {
        cmdrepr = sdscatprintf(cmdrepr,"[%d %s] ",dictid,getClientPeerId(c));
    }

    for (j = 0; j < argc; j++) {
        if (argv[j]->encoding == OBJ_ENCODING_INT) {
            cmdrepr = sdscatprintf(cmdrepr, ""%ld"", (long)argv[j]->ptr);
        } else {
            cmdrepr = sdscatrepr(cmdrepr,(char*)argv[j]->ptr,
                        sdslen(argv[j]->ptr));
        }
        if (j != argc-1)
            cmdrepr = sdscatlen(cmdrepr," ",1);
    }
    cmdrepr = sdscatlen(cmdrepr,"\r\n",2);
    cmdobj = createObject(OBJ_STRING,cmdrepr);

    listRewind(monitors,&li);
    while((ln = listNext(&li))) {
        client *monitor = ln->value;
        addReply(monitor,cmdobj);
    }
    decrRefCount(cmdobj);
}
  1. 调用gettimeofday()方法获取当前时间
  2. 将获取到的时间保存在cmdrepr中
  3. 然后根据client不同的状态,将不同信息追加到cmdrepr中
  4. 遍历传入的所有的参数,将参数添加到cmdrepr中
  5. 将cmdrepr构建成字符串对象
  6. 遍历监控器链表,将命令对象添加到当前监控器的回复中

当客户端把命令发送给服务端的时候,服务器会对这条命令进行处理,同时它还会将命令请求的相关信息发送给监视器,监视器会打印出被监视服务器的命令请求信息。

总结

这里做个小总结,redis监视器的实现比较简单,就是通过Monitor命令修改客户端的标识,然后加入监视器链表中server.monitors,在redis服务器将命令发送完成后,依次遍历监视器链表,将信息发送给链表中的监视器。

到目前为止,redis的大致内容就写到这里了,后面可能会写一些java企业级框架的东西,也可能写点别的内容,拭目以待吧。