在使用redis时,对于相同的数据操作,通过for循环不停的与Redis交互,这样性能不是很好,频繁的与Redis交互,耗时都是在网络中的时间,Redis支持流水线技术,一次性发送所有的数据操作,在redis服务器段一次性执行完成,这样可以大幅度的提高速度。
Demo:
redisTemplate.executePipelined(new SessionCallback<List>() {
@Override
public List execute(RedisOperations operations) throws DataAccessException {
for (int i=0;i<100;i++){
operations.opsForValue().set("pipeline_"+i,i,1,TimeUnit.MINUTES);
}
return null;
}
});
都只是进入队列,然后一次性执行,这样不会马上获取到数据,必须执行完成后才能获取到数据,同样如果进行大批量的数据操作,这样会返回大量执行结果,可能会导致内存溢出,这样的话,还是一个一个的去执行。
如果出现如下报错:
Callback cannot return a non-null value as it gets overwritten by the pipeline
得到的结果为执行后统一返回,所以在回调中不需要设置执行的返回值,lamada中直接返回null即可。
List<Object> result = redisTemplate.executePipelined(new RedisCallback<List<Object>>() {
@Override
public List<Object> doInRedis(RedisConnection connection) throws DataAccessException {
for (int i = 0; i < 10; i++) {
connection.get(("pipeline_" + i).getBytes());
}
return null;
}
});
System.out.println(JSON.toJSONString(result));
Jedis
@Test
public void test06() {
long beginTime = System.currentTimeMillis();
Jedis jedis = new Jedis("192.168.209.101", 6379);
Pipeline pipelined = jedis.pipelined();
for (int i = 0; i < 1000000; i++) {
pipelined.hset("set02", "field" + i, "i");
}
List<Object> objects = pipelined.syncAndReturnAll();
System.out.println(JSON.toJSONString(objects));
System.out.println("耗时:" + (System.currentTimeMillis() - beginTime));
}
Redis中提供了部分批量操作命令,比如hmget,执行时,能保证是原子的。
而流水线模式,进入队列后将会拆分为多个子命令,并且各个子集间可能会间隔其他命令,但是执行的结果还是一样的。
补充说明:
- 注意每次执行pipline时发送的命令个数
参考
https://blog.csdn.net/qfzhangwei/article/details/86005310