以下文章来源于低并发编程 ,作者闪客
./redis-server
宏观上看下我的流程
int main(int argc, char **argv) {
...
initServer();
...
aeCreateFileEvent(fd, acceptHandler, ...);
...
aeMain();
...
}
void aeMain(aeEventLoop *eventLoop)
{
eventLoop->stop = ;
while (!eventLoop->stop)
aeProcessEvents(eventLoop, AE_ALL_EVENTS);
}
展开体验下我的具体工作
redis-cli -h host -p port
static void acceptHandler(...) {
...
cfd = anetAccept(...);
...
c = createClient(cfd))
...
}
static redisClient *createClient(int fd) {
...
aeCreateFileEvent(c->fd, readQueryFromClient, ...);
...
}
void aeMain(aeEventLoop *eventLoop)
{
eventLoop->stop = ;
while (!eventLoop->stop)
aeProcessEvents(eventLoop, AE_ALL_EVENTS);
}
为了方便大家吹牛,我来拔高一下
具体怎么执行一个 Redis 命令
<client 6379> set dibingfa niubi
static struct redisCommand cmdTable[] = {
{"get",getCommand,2,REDIS_CMD_INLINE},
{"set",setCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
{"setnx",setnxCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
{"del",delCommand,-2,REDIS_CMD_INLINE},
{"exists",existsCommand,2,REDIS_CMD_INLINE},
...
}
static void setCommand(redisClient *c) {
...
addReply(c, nx ? shared.cone : shared.ok);
}
static void addReply(redisClient *c, robj *obj) {
...
aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,
sendReplyToClient, c, NULL) == AE_ERR);
}
后记
后记
整篇文章我好像没讲 Redis 为啥那么快,因为我感觉这个问题问得不好。
你可以从接收网络请求的 IO 多路复用角度说起,也可以从事件处理器驱动的 Reactor 模式说起,还可以从具体处理命令时的数据结构说起,比如单单是字符串背后的 sds 其实就做了很多的巧妙设计。
如果我是面试官,我会具体让面试者聊聊 Redis 的启动流程,或者 Redis 处理命令的整个流程。
这里面可挖的点挺多的,如果能谈笑风生,那自然是技术水平还不错。
另外,你会发现本文出现的很多唬人的术语,比如 Reactor 模式,事件处理器等,看一遍 Redis 源码后你会发现真的非常简单。
毫不客气地说,一切丝毫不谈具体实现,和你堆砌一大堆唬人名词的文章或者人,都是在耍流氓。
本文我参考的是 Redis3.0.0 源码,但成文时用的讲解代码是 Redis1.0.0,整个网络模块的设计是完全一样的。