Performance Test Report
Check the performance test report of Ali Redis as follows, can reach hundreds of thousands, millions of levels of QPS (temporarily ignore the optimization of Ali Redis), we from the design and implementation of Redis to analyze how Redis do
Design and implementation of Redis
In fact, Redis mainly meets the performance requirements of such efficient throughput through three aspects
- Efficient data structures
- Multiplexing IO model
- Event mechanism
Efficient data structures
Redis supports several efficient data structures string, hash, list, set, zset
The underlying coding methods of the above exposed data structures have been optimized in different ways, which is not the focus of this paper
Multiplexing IO model
Assuming that 10,000 long connections are established with the Redis server at some point, the practice for blocking IO is to create one thread for each connection to process, so 10,000 threads are needed. Meanwhile, based on our experience, we generally set up for IO intensive operations, Number of threads = 2 * number of cpus + 1. For CPU-intensive operations, generally set the number of threads = NUMBER of cpus + 1. Of course, there is also a detailed calculation formula in various books or on the Internet that can calculate a more appropriate and accurate number of threads, but the result is usually a relatively small value. Systems such as blocking IO, which creates tens of thousands of threads, are not capable of carrying such a load, nor are they capable of efficient throughput and services.
In the multiplexing IO model, a thread is used to put the 10,000 successful links into event_poll one after another. Event_poll registers the callback function for the 10,000 long connections. When a long connection is ready (the establishment is successful, the data is read, etc.), It is written to the ready queue RDList of event_poll via the callback function so that the single thread can fetch the required data by reading the RDList
Note that, except for asynchronous I/O, other I/O models can be classified as blocking I/O models. The difference is that in the blocking I/O model, when data is read in the first phase, if the data is not ready and needs to be blocked, Copying data from kernel to user mode after phase 2 data is ready is also blocked. The multiplexed IO model does not block in the first phase, but only in the second phase
In this way, one or more threads can handle a large number of connections, greatly increasing throughput
The multiplexing I/O model explains why it supports higher concurrency
Event mechanism
The redis client establishes the connection with the Redis server, sends the command, and the Redis server responds to the command through the event mechanism, as shown below.
- First, the Redis server runs and the AE_READABLE event for the listening socket is in the listening state, at which point the connection reply handler works.
- The client initiates a connection with the Redis server and listens for the socket to generate AN AE_READABLE event. When the IO multiplexer detects that it is ready, the AE_READABLE event will be queued. The file event dispatcher will fetch the event from the queue and hand it to the connection reply processor. At the same time, AE_READABLE events of the client socket will be queued and the file event dispatcher will fetch the events in the queue and hand them to the command request handler
- The client sends a set key value request. The AE_READABLE event of the client socket is queued when the IO multiplexer hears that it is ready. The file event dispatcher picks up the event in the queue and hands it to the command request handler for associated processing
- After the command request processor completes the association processing, it needs to respond to the completion of the client operation. At this point, AE_WRITEABLE events that generate sockets are pressed into the queue. The file event dispatcher obtains the events in the queue and hands them to the command recovery processor for processing and returns the operation result. When done, the AE_WRITEABLE event is disassociated from the command recovery handler
Reactor model
Basically, The Reactor model works by matching a queue, using a serverAccept thread to process the connection requests, and using the IO multiplexing model, having the kernel listen on those sockets. Once the read and write events of some sockets are ready, the corresponding events are pressed into the queue. Then the worker works and the file event dispatcher obtains the event from the file event dispatcher and hands it to the corresponding processor for execution. After the execution of an event is completed, the file event dispatcher will obtain the next event from the queue for processing
By default, bossGroup is 1, workerGroup = 2 * number of cpus, so that multiple threads can handle read-write ready events. However, there should be no time-consuming operations. If there are any, they need to be put into the thread pool, otherwise they will reduce the throughput. In Redis we can view both of these values as 1