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等逻辑。