Welcome to pay attention to github.com/hsfxuebao, I hope to help you, if you think it can trouble to click on the Star ha

1. The evolution of Redis

It would be a loose answer to say that Redis is single-threaded or multi-threaded. Different versions of Redis use different threading models.

  1. Version 3.x, the earliest version of redis known by word of mouth, is single-threaded.
  2. Version 4.x is also not strictly single-threaded, but the thread responsible for handling client requests is single-threaded, but starts with a dotMultithreaded stuff (asynchronous deletion)
  3. After the latest version of 6.0.x, farewell to everyone’s impression of single threading, with a brand newmultithreadingTo solve the problem.

2. Redis single-threaded model

2.1 True Meaning of Single Thread

Mainly refers to Redis network IO and key pair reading and writing is completed by a thread, Redis in the processing of client requests, including access (socket read), resolution, execution, content return (socket write) by a sequential main thread processing, this is the so-called “single thread”. This is also the main process for Redis to provide external key and value storage service.

But other Redis features, such asPersistence, asynchronous deletion, cluster data synchronization, and moreIs actually made up ofExtra threadsTo perform. You could say that, RedisThe worker thread is a single thread. However,Redis as a whole is multi-threaded;

2.2 Causes of Fast Single-thread Performance

The main reasons for the fast performance in the Single-threaded Redis 3.x era:

  • Memory-based operations: All data is stored in memory, so all operations are memory level
  • Simple data structures: Redis data structures are specifically designed, and the time to find and manipulate these simple data structures is mostly complexo(1)
  • Multiplexing and fee-blocking IO: Use THE IO multiplexing function to listen for multiple socket connections to clients, so that you can use a thread connection to process multiple requests, reduce the overhead of thread switching, and avoid IO blocking operations
  • Avoid context switching: Because it is a single-threaded model, it can avoid unnecessary previous text switching and multi-threading competition, which can save time and performance consumption caused by multi-threading switching, and single thread does not cause deadlock problems

2.3 The single thread Is adopted

Redis is based on memory, so its bottleneck may be the machine’s memory or network bandwidth rather than CPU, since CPU is not the bottleneck, it is natural to use a single thread solution, and using multiple threads is more troublesome. However, in Redis 4.0, multithreading is supported, such as background deletion. In short, there are three main reasons for single-threading until Redis 4.0:

  1. Using a single-threaded model makes Redis easier to develop and maintain because it is easy to develop and debug; Although multithreaded model has excellent performance in some aspects, it introduces the uncertainty of program execution order, brings a series of problems of concurrent read and write, increases the system complexity, and may cause performance loss caused by thread switching, even locking and unlocking, deadlock. Redis has very high processing performance through AE event model and IO multiplexing, so there is no need to use multithreading. The single-threaded mechanism greatly reduces the complexity of the internal implementation of Redis. Lazy Rehash, Lpush and other “thread-unsafe” commands of Hash can be executed without locking.
  2. Even with the single-threaded model, requests from multiple clients are processed concurrently, mainly using multiplexing and non-blocking IO;
  3. For the Redis system, the mainThe performance bottleneck is memory or network bandwidth, not CPU.

3. Redis multi-threaded model

3.1 Reasons for the introduction of multithreading

If single threading is so good, why multithreading? Single-threading has its own problems, such as large key deletions: The del command normally removes data quickly, but when the deleted key is a very large object, such as a hash set containing thousands of elements, the DEL command causes the Redis main thread to stall.

Therefore, in Redis 4.0, there is a new module for multi-threading. Of course, multi-threading in this version is mainly to solve the problem of low efficiency of deleting data. Lazy delete can effectively avoid the problem of Redis lag (large key deletion and other problems), the steps are as follows:

  1. unlink keyUNLINK removes the set key from the database dictionary if the number of elements in the set key is greater than 64. UNLINK removes the set key from the database dictionary if the number of elements in the set key is greater than 64. UNLINK removes the set key from the database dictionary if the number of elements is greater than 64. If the number of elements is small (less than 64) or is of String type, it is also removed directly from the main thread.
  2. flushall/flushdb asyncFlushdb: for flushdb, add async to make redis flush database asynchronously. The implementation logic is to create a new empty dictionary for the database, the original old database dictionary to the background thread to delete the data one by one, free memory.
  3. The deletion task is handed over to the backend child process to asynchronously delete the data

Because Redis is a single main thread, Antirez always emphasizes “Lazy Redis is better Redis”. The essence of lazy free is to remove some costly operations from the redis main thread and let bio child threads handle them, which greatly reduces the main thread blocking time. This reduces performance and stability issues caused by deletions.

Redis 4.0 introduced multiple threads to achieve asynchronous lazy deletion of data and other functions, but it is still only one thread to process read and write requests, so it is still a narrow sense of single thread.

The main performance bottleneck for Redis is memory or network bandwidth, not CPU. Memory problems are easier to solve, so Redis bottlenecks are due to network IO. Next, introduce the multithreaded model.

3.2 Working principle of multi-threading

The read and write of I/O itself is blocked. For example, when there is data in the socket, Redis will copy the data from the kernel-state space to the user-state space through the call, and then hand over the data to Redis. This copying process is blocked. These operations are done on a single thread basis.

Added in Redis 6.0Multithreading to improve I/O read and write performance, his main implementation idea is to split the main thread IO read and write tasks to a group of independent threads to execute, so that multiple socket read and write can be parallelized, the use of multiplex I/O multiplexing technology can let a single thread efficiently handle multiple connection requests (minimize the network IO time consumption), The most time-consuming Socket reading, request parsing, and writing are outsourced separately, and the rest of the command execution is still executed by the main thread serially and interacts with the data in memory.

According to the above figure,Network data reads and writes, request protocol parsing is handled by multiple IO threads, and for actual command execution, the main thread operation is still used (thread-safe)Is a good compromise. As a result,It is multi-threaded for the entire Redis, but still single-threaded for the worker thread (command execution).

3.3 Workflow

The core process is as follows:

The process is described as follows:

  • The main thread gets the socket and puts it in the wait list
  • Allocate sockets to IO threads (without waiting for list to fill)
  • The main threadBlocking waiting for IO threads (multithreading)Read socket end
  • The main thread executes the command –Single thread(If the command is not received, the SYSTEM waits for the IO to continue next time.)
  • The main threadBlocking waiting for IO threads (multithreading)Write data back to the socket.
  • Unbind and clear the wait queue

Features are as follows:

  • The IO thread is either reading the socket or writing at the same time, but not reading or writing at the same time
  • The IO thread reads and writes socket parsing commands, not commands.
  • Configurable number of IO threads (currently code limit is 512, default is 1(disable this feature))

After the pressure test of interested people, the current performance can be improved more than 1 times.

Question 1: Is the wait list not processed because it has been blocked?

Reply:Blocking checks if the IO thread still has a task. Wait till we’re done before we move on. These tasks are added at execution time, and if the number of tasks is less than the number of threads, then some thread can’t get the task, and its backlog is zero. For a thread that has been assigned a task, its pending will be cleared after processing the I/O event. For a thread that has not been assigned a task, its pending is already 0, so it will not block.This one is still a bit doubtful, who can explain (comment ha)?

3.4 Is multi-threading enabled by default?

In Redis6.0,Multithreading is turned off by defaultIf you want to use multithreading, you need to complete two Settings in redis.conf.

  • Set the IO -thread-do-reads configuration item to yes, indicating that multi-threading is enabled.
  • Set the number of threads. The official recommendation is to set the number of threads to 2 or 3 for a 4-core CPU.For an 8-core CPU, you are advised to set the number of threads to 6The number of threads must be smaller than the number of machine cores. Larger threads are not always better.

4. To summarize

Redis itself started out well, based on memory operation, simple data structure, multiplexing and non-blocking I/O, avoiding unnecessary thread context switching and other features, it is still fast in a single-threaded environment.

However, key deletion of big data is still too slow. Therefore, multi-threaded unlink key/flushall async and other commands are introduced in Redis 4.0, which are mainly used for asynchronous deletion of Redis data.

And in Redis 6.0 introduced I/O multithreaded reading and writing, so that you can deal with more tasks more efficiently, Redis just I/O reading and writing into multithreading, and the execution of the command is still executed by the main thread serial, Therefore, there is no thread-safety problem when operating Redis with multiple threads.

Redis both the original single-threaded design, and now the opposite of multi-threading design, the purpose is only one: to make Redis faster and faster.

Redis 6 is a new feature