Redis Research (18th)-pipelines, redispipeline
The client and Redis use TCP to connect. Whether the client sends a command to Redis or Redis returns the execution result of the command to the client, it must be transmitted over the network. The total time consumption of these two parts is calledRound-trip latency. The round-trip latency varies depending on the network performance. Generally speaking, the local loop address (loop back address) the round-trip latency is equivalent to the time when Redis processes a simple command (such as LPUSH list 1 2 3. If a large number of commands are executed, the round-trip latency of each command may affect the performance.
When executing multiple commands, each command can be executed only after the previous command is executed (that is, the result returned by Redis is received), even if the command does not need the execution result of the previous command. To obtain the title fields in the three keys: post: 1, post: 2, and post: 3, run the following three commands:
The underlying communication protocol of Redis provides support for pipelines. The pipeline can send multiple commands at a time and return the results at a time after execution, when each command in a group of commands does not depend on the execution result of the previous command, the command can be issued together through the pipeline. The pipeline reduces the cumulative round-trip latency by reducing the number of communications between the client and Redis:
The following is a detailed analysis:
Redis is a cs-mode tcp server that uses a request response protocol similar to http. A client can initiate multiple request commands through a socket connection. After each request command is sent, the client usually blocks and waits for the redis service to process it. After redis completes processing, the Request command returns the result to the client through the Response Message. The basic communication process is as follows:
Client: INCR XServer: 1Client: INCR XServer: 2Client: INCR XServer: 3Client: INCR XServer: 4
Basically, four commands require eight tcp packets. Due to network latency, it takes 0.125 seconds to transmit packets from the client to the server. It takes at least one second to complete the eight packets of the preceding four commands. In this way, even if redis can process 100 commands per second, our client can only issue four commands in one second. This shows that redis's processing capabilities are not fully utilized.
In addition to using single commands such as mget and mset to process multiple keys, we can also use pipeline to Package Multiple commands from the client and send them together, the redis server does not need to wait for the response of a single command to return. After processing multiple commands, the redis server will package the processing results of multiple commands and return them to the client.. The communication process is as follows:
Client: INCR XClient: INCR XClient: INCR XClient: INCR XServer: 1Server: 2Server: 3Server: 4
When a large number of operations are performed through pipeline. We can save a lot of time wasted on network latency. You must note that the command is packaged and sent in pipeline mode. redis must cache the processing results of all commands before processing all commands.The more packaged commands, the more memory consumed by the cache. So is it true that the more commands you pack, the better?. Tests are required based on actual conditions. The following is a test of using pipeline on the jedis client:
import redis.clients.jedis.Jedis;import redis.clients.jedis.Pipeline; public class PipelineTest { public static void main(String[] args) { int count = 1000; long start = System.currentTimeMillis(); withoutPipeline(count); long end = System.currentTimeMillis(); System.out.println("withoutPipeline: " + (end-start)); start = System.currentTimeMillis(); usePipeline(count); end = System.currentTimeMillis(); System.out.println("usePipeline: " + (end-start)); } private static void withoutPipeline(int count){ Jedis jr = null; try { jr = new Jedis("10.10.224.44", 6379); for(int i =0; i<count; i++){ jr.incr("testKey1"); } } catch (Exception e) { e.printStackTrace(); } finally{ if(jr!=null){ jr.disconnect(); } } } private static void usePipeline(int count){ Jedis jr = null; try { jr = new Jedis("10.10.224.44", 6379); Pipeline pl = jr.pipelined(); for(int i =0; i<count; i++){ pl.incr("testKey2"); } pl.sync(); } catch (Exception e) { e.printStackTrace(); } finally{ if(jr!=null){ jr.disconnect(); } } }}
Output:
withoutPipeline: 11341usePipeline: 344
The test results are still significantly different. Therefore, using pipeline for multiple operations has obvious advantages.