一、RedisCallback回调
1、使用场景
org.springframework.data.redis.core.RedisCallback
springboot整合redis后, 我们经常使用RedisTemplate 和StringRedisTemplate两个模板类,
但有时候这并不能满足我们的需求, 需要使用 connect 处理, 除了 redisTemplate.getConnection() 之外, 还可以使用callback机制进行处理。
RedisCallback 是一个回调接口,用于在 Redis 连接上执行单个 Redis 命令,并返回执行命令后的结果。使用 RedisCallback 时,需要手动获取 Redis 连接并释放连接资源。RedisTemplate 类提供了一个 execute 方法,用于执行 Redis 命令并返回执行命令后的结果。
2、使用
@Resource(name = "shardedJedisPool")
private ShardedJedisPool shardedJedisPool;
@Override
public <T> T execute(ConnectionCallback<T> action) {
ShardedJedis shardedJedis = null;
try{
// 从连接池中获取jedis分片对象
shardedJedis = shardedJedisPool.getResource();
return action.doInRedis(shardedJedis);
}catch (Exception e){
System.out.println(e.getMessage());
}finally {
if(null != shardedJedis){
shardedJedis.close();
}
}
return null;
}
/**
* attention:真正封装的方法,非常的简洁干脆
*/
public String set(final String key, final String value){
return execute(new ConnectionCallback<String>() {
@Override
public String doInRedis(
ShardedJedis shardedJedis) {
return shardedJedis.set(key, value);
}
});
}
public String get(final String key){
return execute(new ConnectionCallback<String>(){
@Override
public String doInRedis(ShardedJedis shardedJedis) {
return shardedJedis.get(key);
}
});
}
保存:
redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
connection.set(
redisTemplate.getStringSerializer().serialize(
"user.uid." + user.getUid()),
redisTemplate.getStringSerializer().serialize(
user.getAddress()));
return null;
}
});
(2)获取
return redisTemplate.execute(new RedisCallback<User>() {
@Override
public User doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] key = redisTemplate.getStringSerializer().serialize(
"user.uid." + uid);
if (connection.exists(key)) {
byte[] value = connection.get(key);
String address = redisTemplate.getStringSerializer()
.deserialize(value);
User user = new User();
user.setAddress(address);
user.setUid(uid);
return user;
}
return null;
}
});
(3)删除
redisTemplate.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) {
connection.del(redisTemplate.getStringSerializer().serialize(
"user.uid." + uid));
return null;
}
});
二、SessionCallback
SessionCallback 也是一个回调接口,但是它用于在 Spring Redis 的事务上下文中执行多个 Redis 命令。Spring Redis 的事务管理器会为每个事务提供一个独立的 Redis 连接,以保证事务原子性。在使用 SessionCallback 时,可以通过 RedisOperations 接口来执行多个 Redis 命令,这些命令将在同一事务中被执行。
对比维度 | RedisCallback | SessionCallback |
---|---|---|
执行方式 | 逐个执行 Redis 命令 | 将多个 Redis 命令封装在事务内,一次性提交 |
上下文环境 | 使用 RedisTemplate 时需要手动管理 Redis 连接池 | Spring 容器自动管理 Redis 连接池 |
Redis 连接管理 | 手动获取和释放连接 | Spring 自动管理连接 |
返回结果 | 根据具体 Redis 命令返回不同类型的结果 | 返回最后一个 Redis 命令的执行结果 |
执行效率 | 较慢,需要频繁的连接获取和释放 | 快,将多个 Redis 命令封装在一个事务内,减少连接数 |
使用场景 | 需要手动管理 Redis 连接或者执行单个 Redis 命令时 | 需要原子性操作,保证多个 Redis 命令的一致性时 |
三、DefaultedRedisConnection
比如在Spring Cache提到了需要自定义清除cache key,重写evict方法
@Override
public void evict(Object key) {
log.info("key为:{}",key.toString());
if(key instanceof List<?>) {
List<String> keys = (List<String>) key;
//①直接循环调用evict
//keys.forEach( item -> super.evict(item));
//②通过connection批量删除key
byte[][] keysByte = serializeCacheKeys(keys);
this.redisTemplate = getStringRedisTemplate();
this.redisTemplate.execute(
(RedisCallback<Long>)
(connection) -> {
return connection.del(keysByte);
});
}else{
super.evict(key);
}
}