I am Redis and I am 11 years old

Once upon a time I was hot yao pure, hot yao lovely, and now I have betrayed the original “oath”, determined to run all the way in multithreading this road without hesitation, yes, I am your mouth that both lovely and charming Redis, you can call me small R… R 😊.

A wave of SAO operations concluded, we begin today’s text.

We know that multi-threading has been added since Redis 4.0, but isn’t single-threading cool?

Is a single thread slow?

Redis single thread was once our bragging capital, elegant and efficient design, so that countless pursuers are fascinated by it.

You want to know where I rank? Nginx is my big brother, NodeJS is my little brother, and I’m number two in my family.

The three of us are outstanding examples of single threading, demonstrating not only our elegance but also our efficiency.

🙋♂️ Some people may ask: why the single thread of me, unexpectedly so arrogant?

The main reasons why Redis is single threaded but still fast are as follows:

  1. Memory based operation: All data of Redis is stored in memory, so all operations are memory level, so its performance is relatively high;
  2. Simple data structure: Redis data structure is relatively simple, is specially designed for Redis, and these simple data structure search and operation time complexity is O(1), so the performance is relatively high;
  3. Multiplexing and non-blocking I/O: Redis uses I/O multiplexing to listen for multiple socket connections to clients, so that multiple requests can be processed using a single thread connection, reducing the overhead of thread switching and avoiding I/O blocking operations, thus greatly improving Redis performance.
  4. Avoid context switches: Because of the single-threaded model, unnecessary context switches and multi-threaded races are avoided, which saves time and performance costs associated with multi-threaded switches, and single threads do not cause deadlocks.

Redis FAQ (Frequently Asked Questions) answers this single-thread FAQ:

Redis is single threaded. How can I exploit multiple CPU / cores?

It’s not very frequent that CPU becomes your bottleneck with Redis, as usually Redis is either memory or network bound. For instance, using pipelining Redis running on an average Linux system can deliver even 1 million requests per second, so if your application mainly uses O(N) or O(log(N)) commands, it is hardly going to use too much CPU.

However, to maximize CPU usage you can start multiple instances of Redis in the same box and treat them as different servers. At some point a single box may not be enough anyway, so if you want to use multiple CPUs you can start thinking of some way to shard earlier.

You can find more information about using multiple Redis instances in the Partitioning page.

However with Redis 4.0 we started to make Redis more threaded. For now this is limited to deleting objects in the background, and to blocking commands implemented via Redis modules. For future releases, the plan is to make Redis more and more threaded.

See: redis. IO/switchable viewer/FAQ

Redis is based on memory, so its bottleneck may be the machine’s memory or network bandwidth rather than THE CPU. Since the 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;
  2. Even with the single-threaded model, requests from multiple clients are processed concurrently, mainly using multiplexing and non-blocking IO;
  3. For Redis systems, the main performance bottleneck is memory or network bandwidth rather than CPU.


Why multithreading?

However, single thread also has the trouble of single thread. For example, when I (Redis) need to delete a large data, because it is a single line operation at the same step, this will lead to the Redis service delay, so in Redis 4.0, multi-threaded module is added. Of course, multithreading in this version is mainly to solve the problem of low efficiency of deleting data, his related instructions have the following three:

  1. unlink key
  2. flushdb async
  3. flushall async

The following is an example:

> unlink key Delete a key from the background
> OK # Execute successfully
> flushall async # Delete all data
> OK # Execute successfully
Copy the code

So I can “instantly” block these bad guys.

The so-called “instant” deletion is actually a bit of an exaggeration, but the result returned is that the deletion was successful, but this is only to hand over the deletion to the background of the younger (child thread) asynchronous deletion of data.

Tip: When the key is a very large object, such as a hash set containing thousands of elements, the del command will cause the main Redis thread to stall. Therefore, lazy deletion can effectively avoid the problem of Redis lag.

Multithreading in Redis 6

In Redis 4.0, you said that deleting is slow, so you can fool me into turning on (multithreading) to process it. Why does Redis 6.0 require multithreading?

In fact, although multi-threading is introduced in Redis 4.0, it can only be used for asynchronous deletion of large amounts of data. However, it is not very significant for non-deletion operations.

However, if we use multi-threading in a non-delete environment, we can spread the load of Redis synchronous read and write I/O, and make full use of the multi-core CPU resources, which can effectively improve The QPS (Query Per Second) of Redis.

Although Redis uses I/O multiplexing, and is based on non-blocking I/O operation, but I/O read and write itself is blocked, for example, when there is data in the socket, Redis will call to copy the data from the kernel state space to the user state space, and then give Redis call. The copying process is blocked, and the larger the volume of data, the more time it takes to copy, and these operations are done on a single thread.

I/O multiplexing, in simple terms, is a mechanism to ensure that the non-blocking I/O of Redis can be successfully completed by monitoring read/write events of files and notifying threads to perform relevant operations.

Therefore, in Redis 6.0, the function of multithreading is added to improve the read and write performance of I/O. His main implementation idea is to split the IO read and write tasks of the main thread to a group of independent threads to execute, so that multiple socket read and write can be parallelized. But Redis commands are still executed serially by the main thread.

Note that Redis 6.0 disables multi-threading by default. You can enable multi-threading by modifying the IO -threads-do-reads file in Redis redis.conf to true. The complete configuration is set to io-threads-do-reads true. In addition, we also need to set the number of threads to enable the multi-threading function correctly. Also, we need to modify the Redis configuration, for example, set io-Threads 4 to enable 4 threads.

Tip: For a 4-core CPU, the recommended number of threads is 2 or 3. For an 8-core CPU, the recommended number of threads is 6. The number of threads must be smaller than the number of machine cores.

As for the performance of Redis, my father Antirez (author of Redis) mentioned in RedisConf 2019 that the multithreaded I/O feature introduced in Redis 6 has more than doubled the performance increase. Some people in China also used the Redis version with four threads and the single-thread Redis to compare the test in Aliyun, and found that the test results were basically consistent with the conclusion given by AntiRez, and the performance could be basically doubled.

conclusion

Redis is fast in a single-threaded environment, although it relies on its own features such as memory-based operations, simple data structures, multiplexing and non-blocking I/O, and the avoidance of unnecessary thread context switches. However, for big data key deletion or card flying, so in Redis 4.0 introduced multi-threading: Unlink key/flushall async and other commands are mainly used to delete Redis data. In Redis 6.0, I/O multithreaded read and write is introduced, so that more tasks can be processed more efficiently ****. Redis simply changes I/O reading and writing to multithreading, and command execution is still executed sequentially by the main thread, so there is no thread safety problem when operating in multithreading Redis.

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.

So Redis is still the same. He’s still the same kid he was

The last word

Original is not easy, if you think this article is useful to you, please click on a “like”, this is the biggest support and encouragement to the author, thank you.

Follow the public account “Java Chinese community” reply “dry goods”, obtain 50 original dry goods Top list.