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

深入浅出Redis(三)高级特性:管道
http://blog.csdn.net/oyl822/article/details/44460949

Redis是一个响应式的服务,当客户端发送一个请求后,就处于阻塞状态等待Redis返回结果。这样一次命令消耗的时间就包括三个部分:请求从客户端到服务器的时间、结果从服务器到客户端的时间和命令真正执行时间,前两个部分消耗的时间总和称为RTT(Round Trip Time),当客户端与服务器存在网络延时时,RTT就可能会很大,这样就会导致性能问题。管道(Pipeline)就是为了改善这个情况的,利用管道,客户端可以一次性发送多个请求而不用等待服务器的响应,待所有命令都发送完后再一次性读取服务的响应,这样可以极大的降低RTT时间从而提升性能。


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

[java]  view plain  copy
  1. public class App   
  2. {  
  3.     public static void main( String[] args ) {  
  4.         long start = System.currentTimeMillis();  
  5.         withoutPipeline();  
  6.         System.out.println("Without Pipeline takes: " + (System.currentTimeMillis() - start) + " ms.");  
  7.           
  8.         start = System.currentTimeMillis();  
  9.         withPipeline();  
  10.         System.out.println("With Pipeline takes: " + (System.currentTimeMillis() - start) + " ms.");  
  11.     }  
  12.       
  13.     public static void withPipeline() {  
  14.         Jedis jedis = null;  
  15.           
  16.         try {  
  17.             jedis = new Jedis("localhost", 6379);  
  18.             jedis.flushDB();  
  19.             Pipeline p = jedis.pipelined();  
  20.               
  21.             p.set("thekey", Integer.toString(0));  
  22.               
  23.             for (int i = 1; i <= 2000; i++) {  
  24.                 p.incr("thekey");  
  25.             }  
  26.               
  27.             Response<String> r = p.get("thekey");  
  28.               
  29.             p.sync();  
  30.               
  31.             System.out.println(r.get());  
  32.         } finally {  
  33.             jedis.close();  
  34.         }  
  35.           
  36.     }  
  37.       
  38.     public static void withoutPipeline() {  
  39.         Jedis jedis = null;  
  40.           
  41.         try {  
  42.             jedis = new Jedis("localhost", 6379);  
  43.             jedis.flushDB();  
  44.             jedis.set("thekey", Integer.toString(0));  
  45.               
  46.             for (int i = 1; i <= 2000; i++) {  
  47.                 jedis.incr("thekey");  
  48.             }  
  49.               
  50.             System.out.println(jedis.get("thekey"));  
  51.         } finally {  
  52.             jedis.close();  
  53.         }  
  54.           
  55.     }  
  56. }  
  57.   
  58. //输出结果  
  59. 2000  
  60. Without Pipeline takes: 183 ms.  
  61. 2000  
  62. With Pipeline takes: 47 ms.  

结果很直观的反映出两者的差别,要知道这是在本地测试,几乎不存在网络延时的问题,如果是在不同的网段测试的话,效果会更明显。虽然管道在一定程度上对性能有所提升,但是在使用时一点要注意,每个命令的返回结果是先被缓存在服务器端的,最后一次性返回给客户端。如果一次批量提交涉及大量的返回结果,可能会导至服务器的内存溢出,这在生产环境是致命的,一次批次处理多少量,最好在设计阶段做出合理评估。


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

你可能感兴趣的:(深入浅出Redis(三)高级特性:管道)