Databases 20 min read

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.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Why Redis Is Fast: Core Principles and Internal Data Structures

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 response

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

PerformanceRedisdata structuresIn-Memorysingle-threadedIO Multiplexing
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

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.