How does the Redis server work?
I was curious to learn more about Redis’s internals, so I’ve been familiarizing myself with the source, largely by reading and jumping around in Emacs. After I had peeled back enough of the onion’s layers, I realized I was trying to keep track of too many details in my head, and it wasn’t clear how it all hung together. I decided to write out in narrative form how an instance of the Redis server starts up and initializes itself, and how it handles the request/response cycle with a client, as a way of explaining it to myself, hopefully in a clear fashion. Luckily, Redis has a nice, clean code base that is easy to read and follow along. Armed with a TAGSfile, my $EDITOR, and GDB, I set out to see how it all works under the hood. (Incidentally, I was working with the Redis code base as ofcommit b4f2e41. Of course, internals such as I outline below are subject to change. However, the broad architecture of the server is unlikely to change very much, and I tried to keep that in mind as I went along.)
This article examines server startup and takes a high-level view of the request/response processing cycle. In a subsequent article, I’ll dive in to greater detail and trace a simple SET/GET command pair as they make their way through Redis.
Redis: under the hood
Startup
Beginning global server state initialization
Setting up command table
Loading config file
initServer()
Shared objects
Shared integers
Event loop
Databases
TCP socket
Server cron
Registering connection handler with event loop
Opening the AOF
Back up to main()
Restoring data
Event loop setup
Entering the event loop
Processing a request & returning a response
Handling a new connection
Reading a command from a client
Executing the command and responding
Summary
Next time — tracing a SET and GET
Startup
Let’s begin with the main() function in redis.c.
Beginning global server state initialization
First, initServerConfig() is called. This partially initializes a variable server, which has the type struct redisServer, that serves as the global server state.
// redis.h:338 struct redisServer {
pthread_t mainthread; int port; int fd;
redisDb *db;
// ...
};
// redis.c:69 struct redisServer server; /* server global state */
There are a huge number of members in this struct, but they generally fall into the following categories: