SpringBoot使用RedisTemplate.delete刪除指定key失敗的解決辦法
問題概述
關(guān)于這個(gè)問題呢,還是主要出現(xiàn)在項(xiàng)目開發(fā)的管理上面,先描述哈項(xiàng)目環(huán)境:
1、Java 使用的 JDK-1.8
2、Spring Boot 使用的 Spring Boot-2.0.3
3、Redis 使用的是 2.0.8
4、Jedis 使用的是 2.9.0
(當(dāng)然其它就不再描述了)
起先,使用的都是原生的 ReidsTemplate API 進(jìn)行系統(tǒng)緩存的管理工作。后來,由于涉及到對(duì)象相關(guān)的操作,此時(shí)如果還使用原生API,緩存中的對(duì)象是一坨亂碼,讓人眼花繚亂,這是就需要自定義序列化機(jī)制了,而那位同事就默默的添加上了,在團(tuán)隊(duì)中沒有任何的反饋。
當(dāng)然,在系統(tǒng)緩存的管理與操作中,博主依然淡定的使用著 RedisTemplate 原生的 API 呢,然后在某天前,測(cè)試團(tuán)隊(duì)那邊突然就炸開了鍋,各種問題。。。
現(xiàn)象:通過 Redis 的原生 API 刪除緩存中的 Key 后,系統(tǒng)無任何的報(bào)錯(cuò)信息,并提示刪除成功,再進(jìn)入到 Redis 服務(wù)器上查看應(yīng)該被刪除的 Key 依然存在,懵逼了?。?!
解決辦法
經(jīng)過一段艱辛的 BUG 排查,再加上各種姿勢(shì)查看 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 的默認(rèn)序列化機(jī)制 “ defaultSerializer ” ,如果沒有自定義的序列化機(jī)制,則系統(tǒng)默認(rèn)使用的是 “ org.springframework.data.redis.serializer.JdkSerializationRedisSerializer ” ,然后有老鐵又再系統(tǒng)中默默的自定義了 Redis 的序列化機(jī)制,部分示例代碼如下:
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);
// 配置默認(rèn)的序列化器
redisTemplate.setDefaultSerializer(getGenericJackson2JsonRedisSerializer());
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 設(shè)置 Key 的默認(rèn)序列化機(jī)制
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
return redisTemplate;
}
}
在這段代碼中,根據(jù)需求將 Redis Key 的序列化機(jī)制更改為了 “ org.springframework.data.redis.serializer.StringRedisSerializer ” (主要目的為避免出現(xiàn)亂碼的象限,其實(shí)還是能正常的的使用,只是我們?nèi)庋劭吹綖閬y碼而已),并且將 redisTemplate 定義為了類型為泛型的類型。
這兒就是問題的所在,此時(shí)就不能使用原生的 “ RedisTemplate redisTemplate; ” 而需要定義為泛型的 “ RedisTemplate <Object,Object> redisTemplate; ” 了,因?yàn)楫?dāng)我們?cè)俅涡略龅?key 的時(shí)候,使用的是 “ StringRedisSerializer ”序列化機(jī)制,但是在 delete 操作的時(shí)候是使用的是原生 API ,redis 中的 redisTemplate 默認(rèn)序列化機(jī)制采用的是 “ JdkSerializationRedisSerializer ”,這樣以來,即使你使用 hasKey 方法也會(huì)發(fā)現(xiàn) redis 中存在這個(gè) key ,但是實(shí)際 hasKey 返回 false,所以就會(huì)出現(xiàn)刪除成功,但是實(shí)際的數(shù)據(jù)依然存在 Redis 服務(wù)器上咯。
到此這篇關(guān)于SpringBoot使用RedisTemplate.delete刪除指定key失敗的解決辦法的文章就介紹到這了,更多相關(guān)SpringBoot RedisTemplate.delete刪除指定key內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用@Autowired 注入RedisTemplate報(bào)錯(cuò)的問題及解決
- springboot使用redisTemplate操作lua腳本
- SpringBoot整合Redis使用@Cacheable和RedisTemplate
- 使用redisTemplate從redis獲取所有數(shù)據(jù)
- Java使用RedisTemplate如何根據(jù)前綴獲取key列表
- 關(guān)于RedisTemplate之opsForValue的使用說明
- Redis使用RedisTemplate模板類的常用操作方式
- RedisTemplate中opsForValue和opsForList方法的使用詳解
- Redis Template使用詳解示例教程
相關(guān)文章
在 Spring Boot 3 中接入生成式 AI的操作方法
本文介紹了如何在SpringBoot3中集成生成式AI,以O(shè)penAI的GPT模型為例,通過代碼示例展示了如何實(shí)現(xiàn),SpringBoot3的優(yōu)勢(shì)和OpenAI的生成式AI技術(shù)結(jié)合,為開發(fā)者提供了高效集成生成式AI的方法,感興趣的朋友跟隨小編一起看看吧2025-01-01
Spring?Boot?教程之創(chuàng)建項(xiàng)目的三種方式
這篇文章主要分享了Spring?Boot?教程之創(chuàng)建項(xiàng)目的三種方式,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-05-05
Springcloud seata nacos環(huán)境搭建過程圖解
這篇文章主要介紹了Springcloud seata nacos環(huán)境搭建過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
javaBean的基礎(chǔ)知識(shí)及常見亂碼解決方法
這篇文章主要介紹了javaBean的基礎(chǔ)知識(shí)及常見亂碼解決方法的相關(guān)資料,需要的朋友可以參考下2017-03-03
ReentrantLock從源碼解析Java多線程同步學(xué)習(xí)
這篇文章主要為大家介紹了ReentrantLock從源碼解析Java多線程同步學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
Java集合操作之List接口及其實(shí)現(xiàn)方法詳解
這篇文章主要介紹了Java集合操作之List接口及其實(shí)現(xiàn)方法,詳細(xì)分析了Java集合操作中List接口原理、功能、用法及操作注意事項(xiàng),需要的朋友可以參考下2015-07-07

