Backend Development 8 min read

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

.

<code>int main(int argc, char **argv) {
    ...
    initServer();
    ...
    aeCreateFileEvent(fd, acceptHandler, ...);
    ...
    aeMain();
    ...
}</code>

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.

<code>void aeMain(aeEventLoop *eventLoop) {
    eventLoop->stop = 0;
    while (!eventLoop->stop)
        aeProcessEvents(eventLoop, AE_ALL_EVENTS);
}</code>

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

.

<code>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},
    ...
};</code>

After executing the command, the server schedules a reply by attaching

sendReplyToClient

to the client’s writable descriptor using

aeCreateFileEvent

.

<code>static void addReply(redisClient *c, robj *obj) {
    ...
    aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,
        sendReplyToClient, c, NULL);
}</code>

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.

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

login 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.