写在前面: 我们通常是通过使用RedisTemplate每次执行一个命令,这在命令不多的情况下是可以接受的,当我们需要执行大量的命令时,如果一条一条的执行,就会因为通信次数的增加而产生延迟。因此,Redis也引入了pipeline的机制来提升性能,我们可以通过pipeline将所有需要执行的命令,一次性的提交给Redis的服务端,然后挨个执行,这样就会大大的减少通信次数,从而提升性能。当然了,需要注意的是:输入的所有命令中:一个命令的执行结果不影响另一个命令的输入
1、两种调用方式
在Spring环境下,使用Redis的Pipeline也是很简单的:只需要调用redisTemplate的executePipelined方法就可以了,但是在参数中提供了两种回调方式:SessionCallback、RedisCallback,两种使用方式如下:
RedisCallback:
List list = redisTemplate.executePipelined(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection con) throws DataAccessException {
con.set("key".getBytes(StandardCharsets.UTF_8), "value".getBytes(StandardCharsets.UTF_8));
con.set("key2".getBytes(StandardCharsets.UTF_8), "value2".getBytes(StandardCharsets.UTF_8));
con.set("num".getBytes(StandardCharsets.UTF_8), "0".getBytes(StandardCharsets.UTF_8));
con.incr("num".getBytes(StandardCharsets.UTF_8));
return null; // 切记此处要返回null,否则会抛出InvalidDataAccessApiUsageException异常
}
});
System.out.println(Arrays.toString(list.toArray())); // [true, true, true, 1]
SessionCallback:
List list = redisTemplate.executePipelined(new SessionCallback<String>() {
@Override
public String execute(RedisOperations operations) throws DataAccessException {
operations.opsForZSet().intersectAndStore(firstKey, secondKey, destKey);
redisTemplate.opsForZSet().reverseRange(destKey, 0, 10);
return null; // 切记此处要返回null,否则会抛出InvalidDataAccessApiUsageException异常
}
});
区别:
SessionCallback封装的更好一点,对程序员直接调用比较友好;RedisCallback相对而言更加的底层一点,对程序员不是很友好;开发中是推荐使用前者的,即SessionCallback。
2、注意点
需要切记的是回调中的返回值必须是null才可以,否则会抛出InvalidDataAccessApiUsageException异常,相关源码如下:
说到这里,那就有人问了,我需要获取命令返回的值怎么办呢?不得不说这是一个好问题,大家注意下,这个回调的返回值是一个List集合,我们在回调里操作的命令的返回值都依次的被收集到了这个集合中返回了,我们需要哪个命令的返回值,直接在List中拿就可以了,比如例子二中我们需要获取第二条命令返回的Set集合,我们只需要 (Set)list.get(1)即可