Why Redis Is Fast: Core Principles and Internal Data Structures
This article explains why Redis achieves extremely high performance by leveraging pure in‑memory operations, a global O(1) hash table, efficient data structures such as SDS, ziplist, quicklist and skiplist, a single‑threaded event loop with non‑blocking I/O multiplexing, and adaptive encoding strategies.
Redis Overview
Redis is an in‑memory key‑value store that delivers high QPS (up to 100,000 requests per second) by combining several architectural optimizations.
Why Redis Is Fast
Performance stems from three "high" dimensions: high performance (thread model, I/O model, data structures, persistence), high availability (replication, sentinel, cluster), and high scalability (load balancing).
Pure In‑Memory Implementation
All read and write operations happen directly in RAM, avoiding the latency of disk I/O. Memory is accessed via the CPU’s internal memory controller, providing the fastest possible bandwidth.
Efficient Data Structures
Redis uses specialized structures for each data type to maximize speed.
Global Hash Table
All keys are stored in a single global hash table with O(1) lookup. To reduce hash collisions, Redis performs incremental rehashing, gradually moving entries from the old table to a larger new table without blocking the server.
Simple Dynamic String (SDS)
SDS adds a length field for O(1) string length retrieval, pre‑allocates extra space to reduce reallocations, lazily frees unused space, and is binary‑safe, allowing embedded '\0' bytes.
struct SDS {
size_t len; // used length
size_t free; // free space
char buf[]; // actual string data
}Compressed List (ziplist)
Used for small lists, hashes, and sorted sets, ziplist stores entries in a contiguous memory block with fields zlbytes , zltail , zllen , and a terminating zlend . Access to head/tail is O(1); other elements require O(N) traversal.
struct ziplist
{
int32 zlbytes; // total bytes
int32 zltail_offset; // offset of last entry
int16 zllength; // number of entries
T[] entries; // packed entries
int8 zlend; // 0xFF marks end
}Linked List and Quicklist
Traditional doubly‑linked lists provide O(1) insertion/removal at both ends. Modern Redis replaces them with quicklist , a hybrid of linked list nodes each containing a ziplist, combining the benefits of both structures.
Skiplist
Sorted sets (ZSET) use a skiplist (zkiplists) to achieve average O(log N) search while maintaining ordered traversal.
Integer Set (intset)
When a set contains only integers and is small, Redis stores it as an intset for compactness.
typedef struct intset {
uint32_t encoding; // element size (16/32/64 bits)
uint32_t length; // number of elements
int8_t contents[]; // sorted integer array
} intset;Object Encoding
Redis objects ( robj ) contain a type, an encoding, and a pointer to the underlying data structure. Encoding varies per data type (e.g., raw vs. int for strings, ziplist vs. hashtable for hashes, intset vs. hashtable for sets, ziplist vs. zskiplist for sorted sets).
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
void *ptr;
// ... other fields
} robj;Configuration thresholds (e.g., list-max-ziplist-entries 512 , list-max-ziplist-value 64 , zset-max-ziplist-entries 128 , zset-max-ziplist-value 64 ) control when Redis switches between encodings.
Single‑Threaded Model
Redis processes network I/O and command execution in a single thread, while persistence, replication, and background deletions run in auxiliary threads. This eliminates context‑switch overhead, lock contention, and simplifies code.
I/O Multiplexing
Redis uses epoll‑based event multiplexing to handle many client connections in the single thread. System calls such as accept , recv , parse , execute , and send are treated as events, avoiding blocking I/O.
// Simplified I/O handling flow
accept(); // new connection
recv(); // read request
parse(); // parse command
execute(); // run command (e.g., GET)
send(); // write responseSummary of Speed Principles
All operations are memory‑bound, minimizing I/O latency.
A global hash table provides O(1) key lookup, with incremental rehashing to avoid pauses.
Non‑blocking I/O multiplexing lets one thread serve many sockets efficiently.
The single‑threaded design ensures atomicity and removes lock overhead.
Specialized data structures (SDS, ziplist, quicklist, skiplist, intset) optimize storage and access for different workloads.
Adaptive object encoding selects the most efficient representation based on data size and type.
For further reading, see the recommended articles linked at the end of the original source.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
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.