As we all know, Redis is a single-threaded NoSQL database, but is a single-threaded model of Redis why so high performance? That’s what we’re going to explore.

1. Redis single-threaded architecture

1.1 introduction to Redis single thread

First of all, understand that Redis single thread refers to a single thread when executing a command.

The model of Redis client and server side can be simplified as the following figure. Each client call has experienced three processes: sending command, executing command and returning result.

When we talk about single threading, we are talking about executing commands in the second step. A command from the client to the server is not executed immediately, but is placed in a queue and only one instruction is selected for execution at a time.

Sending commands, returning results, and queuing commands are not so simple. For example, Redis uses I/O multiplexing to solve I/O problems.

1.2. Why does Redis use single threads

This is the official explanation: redis. IO /topics/ FAQ

According to the official FAQ, since Redis is a memory-based operation, it is rare for THE CPU to become the bottleneck of Redis. The bottleneck of Redis is most likely memory size or network limitation.

If you want to maximize CPU utilization, you can start multiple instances of Redis on a single machine.

It is worth mentioning that there is such a point of view on the network: the official explanation is a little perfunctory, in fact, because of historical reasons, developers dislike multithreading trouble, and then the use of the CPU was thrown to the user.

At the same time, it is also mentioned in FAQ that after Redis 4.0, it has become multi-threaded. In addition to the main thread, it also has background threads dealing with some relatively slow operations, such as cleaning dirty data, releasing useless connections, deleting big keys and so on.

1.3. Why is single threading so fast

Generally speaking, single-threaded processing power is worse than multi-threaded processing power, so why is Redis using the single-threaded model to achieve 10,000 levels of processing power per second? It boils down to three things:

  • First: pure memory access, Redis puts all the data in memory, and the memory response time is about 100 nanoseconds, which is the most important basis for Redis to achieve 10,000 level of access per second.

  • Second: non-blocking I/O, Redis uses Epoll as the implementation of I/O multiplexing technology, plus Redis’s own event processing model converts epoll connections, reads and writes, and closes into events, so it does not waste too much time on network I/O

Here’s an extension to I/O multiplexing:

To explain what I/O multiplexing is, quote an excellent answer from Zhihu. Suppose you are a teacher and ask 30 students to solve a problem. Then check whether the students have done it correctly. You have the following choices:

  1. First option: check one by one in order, first check A, then B, then C, D… If there is one student stuck, the whole class will be delayed. This mode is as if you were looping through sockets one by one with no concurrency at all.

  2. Option two: You create 30 doppelganger, and each doppelganger checks if a student’s answer is correct. This is similar to creating a process or thread for each user to process the connection.

  3. The third option is, you stand on the stage and whoever answers the question raises their hand. At this time, C and D raise their hands, indicating that they have answered the question, you go down to check the answers of C and D in turn, and then continue to return to the platform. At this point, E and A raise their hands again, and then deal with E and A.

The first is the blocking IO model, and the third is the I/O reuse model. Select, poll, and epoll do this for Linux. Register the FDS of user sockets with epoll, and epoll helps you monitor which sockets are receiving messages, thus avoiding a lot of useless operations. The socket should be in non-blocking mode.

In this way, the entire process blocks only when the select, poll, and epoll calls are called. Sending and receiving customer messages is not blocked, and the entire process or thread is fully used. This is event-driven, called reactor pattern.

  • Third: Single threading avoids the cost of thread switching and races.

Moving on to the final reason why Redis is single-threaded but fast, in multi-threaded development, there are threads to switch and compete, and as a result, there is time to consume. For the program that needs disk I/O, disk I/O is a time-consuming operation. Therefore, for the program that needs disk I/O, we can use multithreading. When a thread is carrying out I/O, the CPU switches to other threads of the current program to reduce the CPU waiting time.

So here’s the question. Redis data is stored in memory, and the CPU still needs to wait for data to be read into the CPU. Why not execute other threads while waiting for data to be read into the CPU to increase CPU usage? The answer to this question is simple, memory reads much slower than CPU, but it is still very fast. It takes a certain amount of time for the CPU to switch threads, and it may take more time to switch threads multiple times than to perform the same task directly with a single thread, which is very uneconomical.

There is also a problem with single threads: there is a requirement for the execution time of each command. If one command is executed too long, it will cause other commands to block, which is fatal for high performance services like Redis, so Redis is a database for fast execution scenarios.

Redis6.0 supports multi-threading

"Isn't Redis single threaded? How come multithreading is supported again?"

I believe that after learning here, this is no longer a problem.

Redis6.0 introduces multithreading, where is this multithreading? Multithreading is used to handle network requests.

Redis 6.0 uses multiple IO threads to process network requests. The resolution of network requests can be completed by other threads, and then the parsed requests are handed over to the main thread for actual memory reading and writing. Improve the parallelism of network request processing, thus improving overall performance.

Are there so many concurrent thread safety issues? — Of course not.

Redis’s multi-IO threads are only used to handle network requests. Redis still uses single threads for command execution.





Reference:

[1] : Redis Development and Operation

[2] : Here comes Redis6.0 support for multithreading

[3] : Why did Redis choose the single-threaded model

[4] : Redis and I/O multiplexing

[5] : What is I/O multiplexing?

[6] : Understand I/O multiplexing and its technology

[7] : Why is Redis single threaded