版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huangjun0210/article/details/84393661
SpringBoot之Redis(四)——Redis流水线
在默认的情况下, Redis 客户端是一条条命令发送给Redis 服务器的,这样显然性能不高。在关系数据库中我们可以使用批量,也就是只有需要执行SQL 时,才一次性地发送所有的SQL 去执行,这样性能就提高了许多。对于Redis 也是可以的,这便是流水线( pipline )技术,在很多情况下并不是Redis 性能不佳,而是网络传输的速度造成瓶颈,使用流水线后就可以大幅度地在需要执行很多命令时提升Redis 的性能。
为测试流水线性能,分别使用单条插入的方式和Redis流水线技术测试100 万次读写的功能实验,单条插入方式的实现代码如下:
@RequestMapping("/testSingle")
public Map<String, Object> testSingle() {
Long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String key = "pipeline_" + i;
String value = "value_" + i;
redisTemplate.opsForValue().set(key, value);
}
Long end = System.currentTimeMillis();
System.out.println("Single插入1000000条记录耗时:" + (end - start) + "毫秒。");
Map<String, Object> map = new HashMap<String, Object>();
map.put("success", true);
return map;
}
使用redis流水线技术实现代码如下:
@RequestMapping("/testPipeline")
public Map<String, Object> testPipeline() {
Long start = System.currentTimeMillis();
List List = redisTemplate.executePipelined(new RedisCallback<Long>() {
@Nullable
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
connection.openPipeline();
for (int i = 1000001; i < 2000000; i++) {
String key = "pipeline_" + i;
String value = "value_" + i;
connection.set(key.getBytes(), value.getBytes());
}
return null;
}
});
Long end = System.currentTimeMillis();
System.out.println("Pipeline插入1000000条记录耗时:" + (end - start) + "毫秒。");
Map<String, Object> map = new HashMap<String, Object>();
map.put("success", true);
return map;
}
分别调用这两个方法。控制台记录的执行时间:
从实验结果可以看出,使用redis流水线插入可以大幅度提高性能,它十分适合大数据量的执行。
这里需要注意的是以下两点。
- 在运行如此多的命令时,需要考虑的另外一个问题是内存空间的消耗,因为对于程序而言,它最终会返回一个List 对象,如果过多的命令执行返回的结果都保存到这个List中,显然会造成内存消耗过大,尤其在那些高并发的网站中就很容易造成JVM内存溢出的异常, 这个时候应该考虑使用迭代的方法执行Redis命令。
- 与事务一样,使用流水线的过程中, 所有的命令也只是进入队列而没有执行,所以执行的命令返回值也为空,这也是需要注意的地方。