- Overview of Redis
Redis (Remote Dictionary Server) is an open-source, high-performance key-value store written in C by Salvatore Sanfilippo. Licensed under the BSD license, it stands out from other caching systems like Memcached due to several core features:
- Persistence: Supports saving in-memory data to disk for recovery after restarts.
- Rich data structures: Beyond simple strings, it offers lists, sets, sorted sets, and hashes.
- High availability: Built-in support for master-slave replication, Sentinel for failover, and native clustering.
As a widely used distributed cache, understanding its source code provides deep insight into system design and performance optimization.
- Development Environment Setup
To explore Redis source code effectively, set up a debugging-friendly environment:
# Verify compiler tools
whereis gcc
whereis g++
On macOS, install necessary toolchains:
xcode-select --install
brew install gcc pkg-config
Clone and prepare the Redis repository:
git clone https://github.com/redis/redis.git
cd redis
git checkout 7.0
For IDE-based debugging (e.g., CLion 2022.3+), import the project using its existing Makefile. To enable debugging symbols and disable optimizations:
make CFLAGS="-g -O0" MALLOC=jemalloc
This generates debuggable binaries in the src/ directory. Configure your IDE to launch redis-server with redis.conf, then connect via redis-cli or Redis Desktop Manager:
redis-cli -h 127.0.0.1 -p 6379
If header files show unresolved references, reload the CMake/Makefile project in your IDE.
- Navigating the Redis Codebase
3.1 Directory Structure
deps/: Third-party dependencies:hiredis: Official C clientjemalloc: High-performance memory allocatorlua: Embedded scripting enginelinenoise: Line editing librayhdr_histogram: Latency tracking
src/: Core implementation (e.g.,server.c, data type handlers)tests/: Unit, integration, and cluster testsutils/: Operational scripts (e.g.,redis-benchmark)redis.conf,sentinel.conf: Default configuration templates
3.2 Recommended Reading Strategy
Two primary approaches exist for studying Redis internals:
- Data structure–first: Dive into implementations of strings, lists, hash tables, etc. This builds foundational knowledge but may overwhelm beginners.
- Execution flow–first: Trace startup (
main()→initServer()) and command execution paths (e.g.,SET→setCommand()). This mirrors real-world usage and eases contextual understanding.
A balanced method is advised: Start by running Redis and issuing basic commands while stepping through the debugger. Once familiar with high-level behavior, investigate specific components like RDB persistence or cluster protocols. Debugging concrete scenarios reinforces comprehension of data structures and control flow.
- Essential C Concepts in Redis
4.1 Macro Definitions
Redis extensively uses #define for constants and inline logic:
#define MAX_CLIENTS 10000
#define MIN(a,b) ((a) < (b) ? (a) : (b))
Note the parentheses around parameters and the entire expression to avoid operator precedence issues during macro expansion.
4.2 Header Files and Modularity
Redis organizes code using header files to declare public interfaces:
// adlist.h
typedef struct listNode { /* ... */ } listNode;
list *listCreate(void);
void listRelease(list *list);
// adlist.c
#include "adlist.h"
list *listCreate(void) { /* implementation */ }
Other modules include "adlist.h" to use these functions, mimicking public API exposure in object-oriented languages.
4.3 Include Guards
To prevent multiple inclusions, headers use guard macros:
#ifndef __REDIS_SDS_H__
#define __REDIS_SDS_H__
// ... declarations ...
#endif
This avoids redefinition errors and reduces compilation overhead. Global state (e.g., the server struct in server.c) is declared as extern in server.h for cross-module access.