记一次Redis
批量删除Key问题
前言
最近在项目中使用redis
时发现一个问题,批量删除的时候删除不了。
代码如下
// redis配置
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
// 批量获取key
@Override
public Set<String> getKeys(String keyPattern) {
return redisTemplate.keys(keyPattern);
}
// 批量删除key
@Override
public void delKeys(Set<String> keys) {
redisTemplate.delete(keys);
}
@Test
public void testDeleteKeys() {
String key="test";
for (int i = 0; i < 5; i++) {
redisObjectService.set(key + i, i);
}
Set<String> keys = redisService.getKeys(key + "*");
redisObjectService.delKeys(keys);
for (int i = 0; i < 5; i++) {
Object o = redisService.get(key + i);
System.out.println(o);
}
}
//输出
0
1
2
3
4
由输出结果可以看出之前存储的键值对并没有删除。
问题原因
经过一番查找得出,redisTemplate
自带的序列化方式是JdkSerializationRedisSerializer
。
而这个序列化方式生成的key会自带一串乱码前缀,如下图所示
而这也正是导致批量删除失败的原因。因为这一串前缀导致匹配不上,故删除不了。
解决方法
知道了问题就很好解决了,只需要换一种redis
序列化 方式,换成StringRedisSerializer
即可。
把redis
配置改成如下即可解决问题。
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(factory);
StringRedisSerializer serializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(serializer);
return redisTemplate;
}
但是改完之后,又出现了另一个问题,由于这是一个springboot
项目,spring boot中有集成redis
缓存。
在使用@cacheable
时如果不指定key,springboot
会选择默认的SimpleKey
类型作为默认的Key,源码如下图:
这就会引发一个类型转换的错误:
org.springframework.cache.interceptor.SimpleKey cannot be cast to java.lang.String
图我就不放了,这时的解决办法是重写keyGenerator
方法
如下代码:
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(factory);
StringRedisSerializer serializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(serializer);
return redisTemplate;
}
@Override
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
};
}
到这里,问题才算完整解决了。