9
头图

We usually see articles introducing Redis, and we all say that Redis is single-threaded. But when we are learning, for example, the bgsave command of Redis, its function is to asynchronously save the data of the current database to disk in the background. Since it is asynchronous, it must be done by other threads. How can we say that Redis is What about single threaded?

In fact, Redis is usually single-threaded, which mainly refers to the main process of Redis providing external key-value storage services, that is, network IO and key-value pair reading and writing are completed by one thread. In addition to other functions of Redis, such as persistence, asynchronous deletion, cluster data synchronization, etc., are performed by additional threads. Node is also the same at this point. It is generally mentioned that Node is also single-threaded, but in fact, Node has only one main thread that is single-threaded, and other asynchronous tasks are completed by other threads. The reason for this is to prevent synchronous code from blocking, which will affect subsequent program code execution after the main thread is occupied.

So strictly speaking Redis is not single threaded. But we generally refer to Redis as single-threaded high-performance, which makes Redis stronger.

Why does Redis use single thread

Why does Redis use single thread? Before answering this question, let's take a look at the familiar database MySQL, which uses multithreading. MySQL does not create a thread every time there is a connection, because too many threads will bring additional overhead, including the overhead of creating and destroying threads, the overhead of scheduling threads, etc., and it will also reduce the overall performance of the computer. This is the difficulty that multithreading will encounter.

In addition, there are usually shared resources accessed by multiple threads at the same time in a multi-threaded system, such as a shared data structure. When multiple processes want to modify this shared resource, in order to ensure the correctness of the shared resource, an additional mechanism is required. Guarantee, and this additional mechanism will also bring additional overhead. Taking MySQL as an example, MySQL introduced a locking mechanism to solve this problem.

It is not difficult to see from the above that concurrent access control in multi-threaded development is a difficult point that requires careful design to handle. If you just deal with it simply, such as simply adopting a coarse-grained mutex, you will only have suboptimal results. Even if threads are added, system throughput will not increase with the number of threads, because most threads are still waiting to acquire mutex locks to access shared resources. Moreover, most of the synchronization primitives introduced by multi-threaded development are used to protect concurrent access to shared resources, which will also reduce the ease of debugging and maintainability of system code.

It is these problems that make Redis adopt the single-threaded mode.

You may be a little confused when you see this. I said earlier that Redis is not a single thread. Now we also said that Redis uses a single thread mode for read and write operations of key-value pairs. So what are its other threads like?

Other threads of the main process

After Redis 3.0 version, in addition to the main thread handling network IO and command operations, there are 3 auxiliary BIO threads in the main process. These three BIO threads are responsible for processing, file closing, AOF buffer data flushing to disk, and three task queues for cleaning objects, so as to avoid the impact of these tasks on the main IO thread.

When Redis starts, it will start these three BIO threads at the same time, but the BIO thread will wake up only when it needs to perform related types of background tasks, and will sleep and wait for tasks at other times.

multi-Progress

In addition to the main process, Redis will fork a child process to handle heavy-duty tasks in the following scenarios:

  • received the bgrewriteaof command: Redis fork a child process, and then the child process writes all commands to rebuild the database state to the temporary AOF file. After writing, the child process will notify the parent process to append the new write operation to the temporary AOF file. Finally replace the old AOF file with the temporary file and rename it.
  • receives the bgsave command: Redis builds a child process, and the child process makes a persistent snapshot of all the data in the memory and writes it to the RDB.
  • When full replication is required: master starts a subprocess, and the subprocess saves the database snapshot to the RDB file. After writing the RDB snapshot file, the master will send the RDB to the slave, and will synchronize subsequent new write instructions to the slave.

Redis6.0 multithreading

Multithreading is a new feature introduced by Redis6.0. As mentioned above, Redis is the core thread responsible for network IO, command processing and writing data to the buffer. With the performance improvement of network hardware, the speed of a single main thread processing network requests cannot keep up with the speed of the underlying network hardware, resulting in network problems. IO processing has become the performance bottleneck of Redis.

And Redis6.0 is from single-threaded processing of network requests to multi-threaded processing, through multiple IO threads to process network operations in parallel to improve the overall processing performance of the instance. It should be noted that for read and write commands, Redis still uses a single thread for processing. This is because continuing to use a single thread to execute command operations eliminates the need to additionally develop multi-threaded mutual exclusion in order to ensure the atomicity of Lua scripts and transactions. mechanism.

It should be noted that in Redis6.0, the multi-threading mechanism is disabled by default, and the following two settings need to be completed in redis.conf to enable multi-threading.

  • Set the io-thread-do-reads configuration item to yes to enable multithreading.
io-threads-do-reads yes
  • Set the number of threads. Generally speaking, the threads is smaller than the number of CPU cores of the machine where the Redis instance is located, For example, for an 8-core machine, Redis officially recommends configuring 6 IO threads.
io-threads 6

Multithreaded process

Let's take a look at how the main thread and IO thread cooperate to complete request processing in Redis6.0.

整体流程示意图

The whole process is divided into the following 4 stages:

Stage 1: The server and the client establish a Socket connection and allocate a processing thread

When a client requests to establish a socket connection with an instance, the main thread will create a connection with the client and put the socket in the global waiting queue. Then the main thread assigns the Socket connection to the IO thread through the polling method.

Stage 2: IO thread reads and parses the request

After the main thread assigns the Socket to the IO thread, it will enter the blocking state and wait for the IO thread to complete the reading and parsing of the client request.

Stage 3: The main thread

After the IO thread finishes parsing the request, the main thread executes these command operations in a single-threaded manner.

Stage 4: IO thread writes back Socket and the main thread clears the global queue

After the main thread performs the requested operation, it will write the result to be returned into the buffer. Then, the main thread will block waiting for the IO thread to write these results back to the Socket and return them to the client. After the IO thread writes back to the Socket, the main thread will clear the global queue and wait for subsequent requests from the client.

Summarize

After reading this article, I believe that everyone has a general idea of the statement that Redis is a single thread. We say it's single-threaded, mainly because in previous versions network IO and key-value reads and writes were done by a single thread. The reason why Redis is multi-threaded is because in versions after Redis 6.0, the part of network IO has become multi-threaded. In addition to the main thread, there are 3 auxiliary BIO threads, namely the fsync thread, the close thread, and the cleaning and recycling thread. Of course, it should not be forgotten that if you want to experience the multi-threading mechanism, you must enable the multi-threading function by modifying the configuration file.

Recommended reading

content repeatedly stolen? to resource misappropriation from the source

Serious Hazard Warning! Log4j Execution Vulnerability Published!


云叔_又拍云
5.9k 声望4.6k 粉丝

又拍云是专注CDN、云存储、小程序开发方案、 短视频开发方案、DDoS高防等产品的国内知名企业级云服务商。