Definition
- In-memory – all data in RAM; ~100ns reads vs ~100us SSD; persistence (RDB/AOF) happens off the hot path.
- Event loop – one thread uses epoll/kqueue to multiplex thousands of sockets; no thread-per-client.
- Zero lock contention – single-threaded execution means no locks, no park/unpark, no context switching on data.
- Atomic by construction – each command completes fully before the next starts.
- Optimized structures – listpack for small collections, skip list for sorted sets; cache-friendly.
- Redis 6.0 I/O threads – parallelize network read/write/parsing; command execution stays on one thread.
One fast head cashier at National Bank of India serves every customer. All ledgers are on the desk (in memory), never fetched from the basement (disk). Because only he touches the ledgers, he never has to lock a drawer against another cashier (no contention) and never shuffles in and out of the chair (no context switching). Redis 6.0 hired assistants to handle the slow paperwork of greeting and sending off customers (network I/O), so the cashier spends all time on the one thing only he can do: updating the ledgers.
Understanding the Concepts
Why is in-memory the biggest factor?
A memory read takes ~100 nanoseconds; an SSD random read ~100 microseconds; a disk seek ~10 milliseconds. Redis is thousands of times faster than a disk-backed store for the same operation. Persistence (snapshots, AOF) runs off the hot path in background/forked processes.
How does the event loop work?
// Conceptual: single-threaded event loop (like Redis's ae.c)
while (running) {
List<Socket> ready = epoll.wait(); // block until data is ready
for (Socket s : ready) {
Command cmd = parse(s.read());
Result r = execute(cmd); // single-threaded, no locks
s.write(r);
}
}
// One thread efficiently handles tens of thousands of connections
// Never wastes time on idle connections
Why does single-threaded execution eliminate lock contention?
In a multi-threaded store, threads touching shared data coordinate with locks. Under load, threads spend time parked waiting and context-switching, burning CPU on coordination. Redis has zero locks because exactly one thread ever touches the data. Counterintuitively, adding threads to the data path would often make Redis SLOWER.
Why are operations atomic without locks?
Because commands execute one at a time, an INCR or LPUSH completes fully before the next command starts. No interleaving, so no need for locks.
// INCR is atomic by construction:
// Client A: INCR counter → 1
// Client B: INCR counter → 2
// Never lost update because commands are serialized
What are the optimized data structures?
| Structure | Internal Encoding | Benefit |
|---|---|---|
| Small hash | listpack (contiguous bytes) | CPU-cache-friendly, no pointer chasing |
| Large hash | hash table | O(1) lookup |
| Sorted set | skip list + hash | O(log N) range + O(1) member lookup |
| Integers | Shared/compact encoding | Less memory |
What did Redis 6.0 add?
I/O threads that parallelize network read/write/parsing across connections. Command execution stays on the single main thread. The lock-free model is preserved.
Redis 6.0 Threading Model
┌────────────────────┐
│ I/O Thread 1 │─── read/parse socket data
│ I/O Thread 2 │─── read/parse socket data
│ I/O Thread 3 │─── write responses
└────────┬───────────┘
│ commands queue
┌────────▼───────────┐
│ Main Thread │─── execute commands (single-threaded, lock-free)
└────────────────────┘
What is dangerous with a single-threaded model?
One slow command (KEYS over millions of keys, large Lua script) blocks the one thread and stalls every other client. Avoid long-running commands on hot instances.
How do you scale CPU across cores?
Run multiple single-threaded Redis instances (Redis Cluster), each on its own core. This keeps each instance lock-free while using all the machine's cores.
What should a senior engineer know?
- Enable I/O threads only when the network is genuinely the bottleneck (many clients, large values).
- The single thread is a feature, not a limitation; adding threads to the data path adds coordination overhead.
- Ban KEYS and long Lua scripts on production instances.
- Scale CPU via Cluster (multiple instances), not by making one instance multi-threaded on the data path.
Visual Overview
Why Redis is Fast ┌───────────────────────────────────────────┐ │ 1. IN-MEMORY: ~100ns vs ~100us (SSD) │ │ 1000x faster than disk-backed stores │ ├───────────────────────────────────────────┤ │ 2. EVENT LOOP: one thread, epoll/kqueue │ │ multiplexes 10,000+ connections │ │ no thread-per-client overhead │ ├───────────────────────────────────────────┤ │ 3. ZERO LOCKS: single thread = no │ │ contention, no context switching │ │ every command atomic by construction │ ├───────────────────────────────────────────┤ │ 4. OPTIMIZED STRUCTURES: listpack, │ │ skip list, shared integers │ ├───────────────────────────────────────────┤ │ 5. Redis 6.0: I/O threads for network │ │ Command execution STAYS single-thread │ └───────────────────────────────────────────┘
Key Takeaway
Redis is fast despite single-threaded command execution because the single-threaded model removes the two biggest costs in concurrent systems: lock contention and context switching. All data is in RAM so reads take ~100ns, not ~100us (SSD) or ~10ms (disk). A single event loop with epoll multiplexes tens of thousands of connections without thread-per-client overhead. And because exactly one thread touches the data, there are no locks, no waiting, and every command is atomic by construction.
Redis 6.0 added I/O threads for network read/write/parsing while keeping command execution on a single thread. The lock-free model is preserved; it is not multi-threaded data access.
At National Bank of India, Pankaj used Redis for microsecond-latency balance and rate-limit lookups. He scaled CPU by running multiple single-threaded instances in a Cluster, and learned the hard way that a KEYS scan over millions of keys stalled every client because it occupied the single thread.
Remember one sentence: Redis is fast because data is in memory, one event loop handles thousands of clients, and single-threaded execution means zero locks and zero context switching, while Redis 6.0 added I/O threads for network work only, preserving the lock-free model.
---