redis源码阅读(三):命令解析和处理

与客户端的连接的回调函数是:readQueryFromClient,读取完数据后调用processInputBuffere,此函数中,先解析出命令,在处理命令;

一.从数据流中解析出命令
readQueryFromClient中读取数据后,调用processInputBuffere;

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");                                                                                    
        }    

REDIS_REQ_INLINE命令类型:
整个命令以 /r/n结尾, 命令的字段以空格间隔, 字段可以包含引号
如:

  set  aaa bbb\r\n
  set "m n" ccc\r\n

REDIS_REQ_MULTIBULK命令类型:
set aaa bbb命令表示如下,

*3\r\n
$3\r\n
set\r\n
$3
aaa\r\n
$3
bbb\r\n

其中,*3表示命令set aaa bbb一共有三个字段,$3表示当前字段的长度为3:

processInlineBuffer或者processMultibulkBuffer执行后,
参数个数保留在c->argc中,所有参数以redisObject结构保存在数组c->argv中;

二.处理命令
processInputBuffere中解析出命令后,调用processCommand处理保存在c->argc,c->argv中的命令;

  /* 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);                                                                                                    
        }                                                                                                                          
     }      

如果是集群模式,processCommand中会判断,所有的key是否都在当前节点,如果不是,返回重定向命令;

    /* If cluster is enabled perform the cluster redirection here.
     * However we don't perform the redirection if:
     * 1) The sender of this command is our master.
     * 2) The command has no key arguments. */
    if (server.cluster_enabled &&
        !(c->flags & REDIS_MASTER) &&
        !(c->flags & REDIS_LUA_CLIENT &&
          server.lua_caller->flags & REDIS_MASTER) &&
        !(c->cmd->getkeys_proc == NULL && c->cmd->firstkey == 0))
    {    
        int hashslot;

        if (server.cluster->state != REDIS_CLUSTER_OK) {
            flagTransaction(c);
            clusterRedirectClient(c,NULL,0,REDIS_CLUSTER_REDIR_DOWN_STATE);
            return REDIS_OK;
        } else {
            int error_code;
            clusterNode *n = getNodeByQuery(c,c->cmd,c->argv,c->argc,&hashslot,&error_code);
            if (n == NULL || n != server.cluster->myself) {
                flagTransaction(c);
                clusterRedirectClient(c,n,hashslot,error_code);
                return REDIS_OK;
            }    
        }    
    }    

命令执行:当前客户端如果在执行事务,而且当前命令不是事务中的multi,exe,watch,discard命令,则把命令缓存起来;否则,调用call(c,REDIS_CALL_FULL);执行当前命令;参考redis的设计与实现.事务.

    /* Exec the command */
    if (c->flags & REDIS_MULTI &&
        c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&
        c->cmd->proc != multiCommand && c->cmd->proc != watchCommand)
    {
        queueMultiCommand(c);
        addReply(c,shared.queued);
    } else {
        call(c,REDIS_CALL_FULL);
        c->woff = server.master_repl_offset;
        if (listLength(server.ready_keys))
            handleClientsBlockedOnLists();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值