Redis 命令处理流程 - leeqx/leeqx.github.io GitHub Wiki

Redis 命令处理流程

在上一篇redis的文章中,大致解释了redis 网络处理流程。[redis网络模型] (https://github.com/leeqx/leeqx.github.io/wiki/Redis-%E7%BD%91%E7%BB%9C%E4%BA%8B%E4%BB%B6) 本章主要梳理一下redis 受到request的整个处理流程。 在redis.c 上篇中看到了,网络接受完成之后调用processInputBuffer处理业务逻辑。在该方法中掉会对单条命令和多条命令区分处理:

void processInputBuffer(redisClient *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;
       } 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);
         }
      } 
}
int processCommand(redisClient *c) {
...
  c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr); 
...
   /* 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();
     }   
}

肯定很好奇call 这里调用的是什么方法? 其实稍微简单想一下其实这里就是调用每个redis命令相关的回调方法。比如set 这个命令,我们在 redis.c 可以看到每个命令都配置这一个对应的回调方法,lookupCommand() 就是获取对应命令的回调方法,在call中将会调用 c->cmd->proc (即使对应的配置的回调方法) .比如下面的:getCommand setCommand

   struct redisCommand redisCommandTable[] = {    
          {"get",getCommand,2,"rF",0,NULL,1,1,1,0,0},
          {"set",setCommand,-3,"wm",0,NULL,1,1,1,0,0}, 
       .....
   };

另外在call()方法中不光调用回调方法,还会根据对应的命令是否需要触发写aof、或者是否需要同步到slave等逻辑。