How Redis Starts: Inside the Server’s Event Loop and Reactor Model
This article walks through Redis's startup sequence, explaining how the server creates a listening socket, registers events with the aeFileEvent system, runs a single‑threaded select‑based event loop, and processes client commands using the Reactor pattern, complete with code examples and diagrams.
Macro View of the Process
When the Redis server binary ( ./redis-server) is executed, the main function initializes the server, creates a TCP listening socket, registers it with aeCreateFileEvent, and then enters the event loop via aeMain.
int main(int argc, char **argv) {
...
initServer();
...
aeCreateFileEvent(fd, acceptHandler, ...);
...
aeMain();
...
}The startup can be seen as three main steps:
Step 1 – Create a TCP listening socket
The server calls listenToPort(), which performs the classic socket‑bind‑listen sequence and returns a file descriptor.
Step 2 – Register the listening descriptor
The descriptor is added to the aeFileEvent list via aeCreateFileEvent() and bound to the acceptHandler callback.
Step 3 – Run the event loop
aeMain()repeatedly calls aeProcessEvents(eventLoop, AE_ALL_EVENTS), using select (IO multiplexing) to monitor all registered descriptors.
void aeMain(aeEventLoop *eventLoop) {
eventLoop->stop = 0;
while (!eventLoop->stop)
aeProcessEvents(eventLoop, AE_ALL_EVENTS);
}When a client connects, acceptHandler creates a dedicated redisClient and registers its read event with aeCreateFileEvent. Subsequent client commands are processed by readQueryFromClient, which looks up the command in the cmdTable (command pattern) and dispatches to the appropriate implementation such as setCommand.
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},
...
};After executing the command, the server schedules a reply by attaching sendReplyToClient to the client’s writable descriptor using aeCreateFileEvent.
static void addReply(redisClient *c, robj *obj) {
...
aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,
sendReplyToClient, c, NULL);
}This design follows the Reactor pattern: a single thread monitors I/O events, and each event is handled by a specific callback, ensuring sequential command execution without the need for locking.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
