高防服务器

SpringBoot使用RedisTemplate.delete删除指定key失败怎么解决


SpringBoot使用RedisTemplate.delete删除指定key失败怎么解决

发布时间:2022-03-23 17:45:26 来源:高防服务器网 阅读:66 作者:iii 栏目:开发技术

本篇内容介绍了“SpringBoot使用RedisTemplate.delete删除指定key失败怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

问题概述

关于这个问题呢,还是主要出现在项目开发的管理上面,先描述哈项目环境:

1、Java 使用的 JDK-1.8

2、Spring Boot 使用的 Spring Boot-2.0.3

3、Redis 使用的是 2.0.8

4、Jedis 使用的是 2.9.0

(当然其它就不再描述了)

起先,使用的都是原生的 ReidsTemplate API 进行系统缓存的管理工作。后来,由于涉及到对象相关的操作,此时如果还使用原生API,缓存中的对象是一坨乱码,让人眼花缭乱,这是就需要自定义序列化机制了,而那位同事就默默的添加上了,在团队中没有任何的反馈。

当然,在系统缓存的管理与操作中,博主依然淡定的使用着 RedisTemplate 原生的 API 呢,然后在某天前,测试团队那边突然就炸开了锅,各种问题。。。

现象:通过 Redis 的原生 API 删除缓存中的 Key 后,系统无任何的报错信息,并提示删除成功,再进入到 Redis 服务器上查看应该被删除的 Key 依然存在,懵逼了!!!

解决办法

经过一段艰辛的 BUG 排查,再加上各种姿势查看 Redis 源码,终于把问题给解决了,贴上一段 Redis 源码如下:

    public void afterPropertiesSet() {          super.afterPropertiesSet();          boolean defaultUsed = false;          if (this.defaultSerializer == null) {              this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());          }             if (this.enableDefaultSerializer) {              if (this.keySerializer == null) {                  this.keySerializer = this.defaultSerializer;                  defaultUsed = true;              }                 if (this.valueSerializer == null) {                  this.valueSerializer = this.defaultSerializer;                  defaultUsed = true;              }                 if (this.hashKeySerializer == null) {                  this.hashKeySerializer = this.defaultSerializer;                  defaultUsed = true;              }                 if (this.hashValueSerializer == null) {                  this.hashValueSerializer = this.defaultSerializer;                  defaultUsed = true;              }          }             if (this.enableDefaultSerializer && defaultUsed) {              Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");          }             if (this.scriptExecutor == null) {              this.scriptExecutor = new DefaultScriptExecutor(this);          }             this.initialized = true;      }

《 Redis 源码地址 》

注意到 Redis 的默认序列化机制 “ defaultSerializer ” ,如果没有自定义的序列化机制,则系统默认使用的是 “ org.springframework.data.redis.serializer.JdkSerializationRedisSerializer ” ,然后有老铁又再系统中默默的自定义了 Redis 的序列化机制,部分示例代码如下:

package com.btc.common.config;     import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;  import org.springframework.cache.CacheManager;  import org.springframework.cache.annotation.CachingConfigurerSupport;  import org.springframework.cache.annotation.EnableCaching;  import org.springframework.context.annotation.Bean;  import org.springframework.context.annotation.Configuration;  import org.springframework.data.redis.cache.RedisCacheManager;  import org.springframework.data.redis.connection.RedisConnectionFactory;  import org.springframework.data.redis.core.RedisTemplate;  import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;  import org.springframework.data.redis.serializer.StringRedisSerializer;        @Configuration  @EnableCaching  public class RedisConfig          extends CachingConfigurerSupport  {      @Bean      public CacheManager cacheManager(final RedisConnectionFactory redisConnectionFactory)      {          RedisCacheManager.RedisCacheManagerBuilder builder                  = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory);             return builder.build();      }         @Bean(name = "springSessionDefaultRedisSerializer")      public GenericJackson2JsonRedisSerializer getGenericJackson2JsonRedisSerializer()      {          return new GenericJackson2JsonRedisSerializer();      }         @Bean      @ConditionalOnMissingBean(name = "redisTemplate")      public RedisTemplate<Object, Object> getRedisTemplate(              final RedisConnectionFactory connectionFactory      )      {          RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();          redisTemplate.setConnectionFactory(connectionFactory);          // 配置默认的序列化器          redisTemplate.setDefaultSerializer(getGenericJackson2JsonRedisSerializer());          StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();          // 设置 Key 的默认序列化机制          redisTemplate.setKeySerializer(stringRedisSerializer);          redisTemplate.setHashKeySerializer(stringRedisSerializer);          return redisTemplate;      }  }

在这段代码中,根据需求将 Redis Key 的序列化机制更改为了 “ org.springframework.data.redis.serializer.StringRedisSerializer ” (主要目的为避免出现乱码的象限,其实还是能正常的的使用,只是我们肉眼看到为乱码而已),并且将 redisTemplate 定义为了类型为泛型的类型。

这儿就是问题的所在,此时就不能使用原生的 “ RedisTemplate redisTemplate; ” 而需要定义为泛型的 “ RedisTemplate <Object,Object> redisTemplate; ” 了,因为当我们再次新增的 key 的时候,使用的是 “ StringRedisSerializer ”序列化机制,但是在 delete 操作的时候是使用的是原生 API ,redis 中的 redisTemplate 默认序列化机制采用的是 “ JdkSerializationRedisSerializer ”,这样以来,即使你使用 hasKey 方法也会发现 redis 中存在这个 key ,但是实际 hasKey 返回 false,所以就会出现删除成功,但是实际的数据依然存在 Redis 服务器上咯。

“SpringBoot使用RedisTemplate.delete删除指定key失败怎么解决”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注高防服务器网网站,小编将为大家输出更多高质量的实用文章!

[微信提示:高防服务器能助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

[图文来源于网络,不代表本站立场,如有侵权,请联系高防服务器网删除]
[