• 深入浅出Redis(三)高级特性:管道


    Redis是一个响应式的服务,当client发送一个请求后,就处于堵塞状态等待Redis返回结果。

    这样一次命令消耗的时间就包含三个部分:请求从client到server的时间、结果从server到client的时间和命令真正运行时间,前两个部分消耗的时间总和称为RTT(Round Trip Time)。当client与server存在网络延时时,RTT就可能会非常大,这样就会导致性能问题。

    管道(Pipeline)就是为了改善这个情况的。利用管道,client能够一次性发送多个请求而不用等待server的响应,待全部命令都发送完后再一次性读取服务的响应,这样能够极大的减少RTT时间从而提升性能。


    以下这个样例。在本地分别以普通请求和管道对一个键调用2000次incr命令的測试。

    public class App 
    {
    	public static void main( String[] args ) {
    		long start = System.currentTimeMillis();
    		withoutPipeline();
    		System.out.println("Without Pipeline takes: " + (System.currentTimeMillis() - start) + " ms.");
    		
    		start = System.currentTimeMillis();
    		withPipeline();
    		System.out.println("With Pipeline takes: " + (System.currentTimeMillis() - start) + " ms.");
    	}
    	
        public static void withPipeline() {
        	Jedis jedis = null;
        	
        	try {
        		jedis = new Jedis("localhost", 6379);
        		jedis.flushDB();
        		Pipeline p = jedis.pipelined();
            	
            	p.set("thekey", Integer.toString(0));
            	
            	for (int i = 1; i <= 2000; i++) {
            		p.incr("thekey");
            	}
            	
            	Response<String> r = p.get("thekey");
            	
            	p.sync();
            	
            	System.out.println(r.get());
        	} finally {
        		jedis.close();
        	}
        	
        }
        
        public static void withoutPipeline() {
        	Jedis jedis = null;
        	
        	try {
        		jedis = new Jedis("localhost", 6379);
        		jedis.flushDB();
        		jedis.set("thekey", Integer.toString(0));
            	
            	for (int i = 1; i <= 2000; i++) {
            		jedis.incr("thekey");
            	}
            	
            	System.out.println(jedis.get("thekey"));
        	} finally {
        		jedis.close();
        	}
        	
        }
    }
    
    //输出结果
    2000
    Without Pipeline takes: 183 ms.
    2000
    With Pipeline takes: 47 ms.

    结果非常直观的反映出两者的区别。要知道这是在本地測试,差点儿不存在网络延时的问题。假设是在不同的网段測试的话,效果会更明显。

    尽管管道在一定程度上对性能有所提升,可是在使用时一点要注意。每一个命令的返回结果是先被缓存在server端的,最后一次性返回给client。假设一次批量提交涉及大量的返回结果,可能会导至server的内存溢出。这在生产环境是致命的。一次批次处理多少量,最好在设计阶段做出合理评估。


    最后,管道仅仅是一个方案。并不意味着在不论什么时候都要尽可能的使用它。而是应该结合考虑网络延迟时间、业务涉及的请求量等等因素综合考虑。毕竟创建管道本身也会有一定的消耗。


  • 相关阅读:
    [BZOJ 2144]跳跳棋
    [NOIp 2015]信息传递
    [JLOI 2014]松鼠的新家
    [Luogu 2062]分队问题
    [Luogu 2090]数字对
    [NOIp 2015]运输计划
    [USACO 03FEB]Farm Tour
    [TJOI 2010]中位数
    IO密集型 计算密集型
    python 编码
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6821938.html
Copyright © 2020-2023  润新知