Databases 17 min read

Is Redis Really Single‑Threaded? Exploring Redis 6.0 Multithreading and Bottlenecks

The article explains why Redis has traditionally been single‑threaded, details the new IO‑thread multithreading model introduced in Redis 6.0, walks through its four processing stages, lists essential INFO monitoring commands, examines memory overhead of strings versus hashes, compares List and Sorted Set ordering, and identifies five key performance‑blocking points.

Shepherd Advanced Notes
Shepherd Advanced Notes
Shepherd Advanced Notes
Is Redis Really Single‑Threaded? Exploring Redis 6.0 Multithreading and Bottlenecks

1. Is Redis Really Single‑Threaded?

Redis has long been known for its single‑threaded architecture, handling network I/O, request parsing, and command execution in one thread. In Redis 6.0 a new multithreading feature was added to offload network I/O to multiple IO threads while keeping command execution single‑threaded to preserve atomicity of Lua scripts and transactions.

The interaction between the main thread and the IO threads can be divided into four stages:

Connection establishment: The main thread accepts incoming socket connections, creates a socket object, and places it in a global pending queue. It then dispatches the socket to an IO thread using a round‑robin poll.

IO thread reads and parses the request: After a socket is assigned, the main thread blocks waiting for the IO thread to finish reading and parsing. Multiple IO threads work in parallel, so this step completes quickly.

Main thread executes the command: Once parsing is done, the main thread processes the command in the traditional single‑threaded manner.

IO thread writes the response: After the command finishes, the main thread writes the result into a buffer and blocks until an IO thread flushes the buffer back to the socket. Multiple IO threads again handle the write concurrently, after which the main thread clears the global queue and waits for the next request.

Configuration to enable multithreading (disabled by default) requires two settings in redis.conf: io-threads-do-reads yes and setting the number of IO threads, typically less than the CPU core count (e.g., 6 threads on an 8‑core machine): io-threads 6 If CPU usage is low but throughput does not improve, enabling the multithreaded I/O can accelerate network handling and increase overall throughput.

Redis multithreading stages diagram
Redis multithreading stages diagram
Main thread and IO thread interaction diagram
Main thread and IO thread interaction diagram

2. Comprehensive Monitoring with the INFO Command

The basic monitoring command is INFO. It can take an optional section argument to return specific categories of metrics. The author groups the output into five major categories, each containing sub‑sections.

Key sections to watch in both standalone and clustered deployments are:

stat , commandstat , cpu , and memory – provide command execution counts, CPU usage, and memory consumption.

persistence – shows RDB and AOF status when those features are enabled.

replication – displays real‑time master‑slave synchronization details.

Because INFO returns plain text, third‑party tools such as Prometheus can scrape and visualize these metrics via exporters.

INFO command sections
INFO command sections

3. Why String Keys Consume More Memory Than Expected

When storing simple values with the String type, Redis adds metadata (length, allocation flags, etc.) via the Simple Dynamic String (SDS) structure and a redisObject header that also stores reference count, last access time, and type information. For small payloads this overhead can dominate the actual data size.

Two hash‑based alternatives are suggested:

Use a plain hash where the field names are fixed; however, large hashes can become “bigkeys”.

Apply a two‑level encoding: split a single value into a hash key (e.g., the first 7 digits of an image ID) and hash fields (the remaining digits and a related object ID). This spreads the data across multiple hash entries and avoids a single massive key.

4. List vs. Sorted Set Ordering

List

preserves insertion order, while Sorted Set orders elements by a numeric score. For pagination scenarios where new items are continuously added, a List can cause duplicate reads, whereas a Sorted Set can retrieve items in exact score order using ZRANGEBYSCORE, ensuring consistent ordering even with frequent updates.

5. Identifying and Mitigating Redis Blocking Points

The author outlines five major sources of main‑thread blocking:

Client‑side operations: Network I/O is handled by the event loop, so it does not block. However, command complexity O(N) (e.g., HGETALL, SMEMBERS, set aggregations) can stall the main thread.

Big‑key deletions: Deleting large collections is costly. Benchmarks show deletion time grows from 5× to nearly 20× when element count rises from 100 k to 1 M, with the worst case (Hash with 1 M elements) taking about 1.98 s, far exceeding Redis’s typical microsecond latency.

Database flushes: Commands like FLUSHDB and FLUSHALL remove all keys, incurring the same memory‑release overhead as big‑key deletions.

AOF rewrite and fsync: AOF rewriting generates heavy disk I/O in a background child process, but the main thread must wait for fsync to complete. When AOF rewrite pressure is high, fsync can block the main thread for 1–2 ms per write.

Cluster migration and replication: In Redis Cluster, the master generates RDB files in a child process, but a replica must FLUSHDB before loading the RDB, hitting the flush‑block point. Loading large RDB files also blocks the replica.

For Redis versions ≥4.0, asynchronous sub‑threads can handle big‑key deletions and flushes. For older versions, the author recommends using SCAN to iterate and delete keys in small batches, reducing the impact on the main thread.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Memory optimizationRedismultithreadingIO threadsINFO commandBlocking operations
Shepherd Advanced Notes
Written by

Shepherd Advanced Notes

Dedicated to sharing advanced Java technical insights, daily work snippets, and the power of persistent effort.

0 followers
Reader feedback

How this landed with the community

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.