redis流水线处理、降低响应时间
在事务中 Redis 提供了队列,这是一个可以批量执行任务的队列,这样性能就比较高,但是使用 multi...exec 事务命令是有系统开销的,因为它会检测对应的锁和序列化命令。
有时候我们希望在没有任何附加条件的场景下去使用队列批量执行一系列的命令,从而提高系统性能,这就是 Redis 的流水线(pipelined)技术。而现实中 Redis 执行读/写速度十分快,而系统的瓶颈往往是在网络通信中的延时,如下图所示:
以下使用测试代码直观感受下响应时间的区别:
测试1000条命令的响应时长。
一、非流水线方式执行(耗时:23796毫秒)
1 @Test//不开启流水线 2 public void testJedisPool2() { 3 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); 4 JedisPool jedisPool = new JedisPool(jedisPoolConfig, "aliyun", 6379, 5000, Value.PASSWORD); 5 6 Jedis jedis = jedisPool.getResource(); 7 8 long start = System.currentTimeMillis(); 9 // 这里测试500条的读/写2个操作 10 for (int i = 0; i < 500; i++) { 11 int j = i + 1; 12 String s1 = jedis.set("pipeline_key_" + j, "pipeline_value_" + j); 13 String s2 = jedis.get("pipeline_key_" + j); 14 } 15 long end = System.currentTimeMillis(); 16 // 计算耗时 17 System.err.println("耗时:" + (end - start) + "毫秒");//耗时:23796毫秒 18 19 jedis.close(); 20 jedisPool.close(); 21 }
二、流水线方式执行(耗时:109毫秒)
1 @Test//连接池连接 2 public void testJedisPool() { 3 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); 4 JedisPool jedisPool = new JedisPool(jedisPoolConfig, "aliyun", 6379, 5000, Value.PASSWORD); 5 6 Jedis jedis = jedisPool.getResource(); 7 8 long start = System.currentTimeMillis(); 9 // 开启流水线 10 Pipeline pipeline = jedis.pipelined(); 11 // 这里测试500条的读/写2个操作 12 for (int i = 0; i < 500; i++) { 13 int j = i + 1; 14 pipeline.set("pipeline_key_" + j, "pipeline_value_" + j); 15 pipeline.get("pipeline_key_" + j); 16 } 17 // pipeline.sync(); //这里只执行同步,但是不返回结果 18 // pipeline.syncAndReturnAll ();将返回执行过的命令返回的List列表结果 19 List result = pipeline.syncAndReturnAll(); 20 long end = System.currentTimeMillis(); 21 // 计算耗时 22 System.err.println("耗时:" + (end - start) + "毫秒");//耗时:109毫秒 23 24 jedis.close(); 25 jedisPool.close(); 26 }
可以明显的感觉到其性能差别。所以在执行大批量的命令时,可以考虑采用这种流水线的方式。
There are two things to do in a day: a happy thing and a difficult one.