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.

macrozheng
macrozheng
macrozheng
How Redis Starts: Inside the Server’s Event Loop and Reactor Model

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend DevelopmentredisNetwork programmingReactor Patternevent loopSingle Thread
macrozheng
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.