SpringBoot使用RedisTemplate.delete刪除指定key失敗的解決辦法
問題概述
關(guān)于這個問題呢,還是主要出現(xiàn)在項目開發(fā)的管理上面,先描述哈項目環(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
(當然其它就不再描述了)
起先,使用的都是原生的 ReidsTemplate API 進行系統(tǒng)緩存的管理工作。后來,由于涉及到對象相關(guān)的操作,此時如果還使用原生API,緩存中的對象是一坨亂碼,讓人眼花繚亂,這是就需要自定義序列化機制了,而那位同事就默默的添加上了,在團隊中沒有任何的反饋。
當然,在系統(tǒng)緩存的管理與操作中,博主依然淡定的使用著 RedisTemplate 原生的 API 呢,然后在某天前,測試團隊那邊突然就炸開了鍋,各種問題。。。
現(xiàn)象:通過 Redis 的原生 API 刪除緩存中的 Key 后,系統(tǒng)無任何的報錯信息,并提示刪除成功,再進入到 Redis 服務(wù)器上查看應(yīng)該被刪除的 Key 依然存在,懵逼了?。?!
解決辦法
經(jīng)過一段艱辛的 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 ” ,如果沒有自定義的序列化機制,則系統(tǒng)默認使用的是 “ org.springframework.data.redis.serializer.JdkSerializationRedisSerializer ” ,然后有老鐵又再系統(tǒng)中默默的自定義了 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(); // 設(shè)置 Key 的默認序列化機制 redisTemplate.setKeySerializer(stringRedisSerializer); redisTemplate.setHashKeySerializer(stringRedisSerializer); return redisTemplate; } }
在這段代碼中,根據(jù)需求將 Redis Key 的序列化機制更改為了 “ org.springframework.data.redis.serializer.StringRedisSerializer ” (主要目的為避免出現(xiàn)亂碼的象限,其實還是能正常的的使用,只是我們?nèi)庋劭吹綖閬y碼而已),并且將 redisTemplate 定義為了類型為泛型的類型。
這兒就是問題的所在,此時就不能使用原生的 “ RedisTemplate redisTemplate; ” 而需要定義為泛型的 “ RedisTemplate <Object,Object> redisTemplate; ” 了,因為當我們再次新增的 key 的時候,使用的是 “ StringRedisSerializer ”序列化機制,但是在 delete 操作的時候是使用的是原生 API ,redis 中的 redisTemplate 默認序列化機制采用的是 “ JdkSerializationRedisSerializer ”,這樣以來,即使你使用 hasKey 方法也會發(fā)現(xiàn) redis 中存在這個 key ,但是實際 hasKey 返回 false,所以就會出現(xiàn)刪除成功,但是實際的數(shù)據(jù)依然存在 Redis 服務(wù)器上咯。
到此這篇關(guān)于SpringBoot使用RedisTemplate.delete刪除指定key失敗的解決辦法的文章就介紹到這了,更多相關(guān)SpringBoot RedisTemplate.delete刪除指定key內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用@Autowired 注入RedisTemplate報錯的問題及解決
- 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)文章
javaweb servlet中使用請求轉(zhuǎn)發(fā)亂碼的實現(xiàn)
下面小編就為大家?guī)硪黄猨avaweb servlet中使用請求轉(zhuǎn)發(fā)亂碼的實現(xiàn)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-08-08java.lang.StackOverflowError出現(xiàn)的原因及解決
這篇文章主要介紹了java.lang.StackOverflowError出現(xiàn)的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07IntelliJ IDEA2019 安裝lombok的實現(xiàn)
這篇文章主要介紹了IntelliJ IDEA2019 安裝lombok的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-10-10Java如何使用itext向PDF插入數(shù)據(jù)和圖片
最近項目中使用到Java實現(xiàn)寫入PDF文件,這篇文章主要給大家介紹了關(guān)于Java如何使用itext向PDF插入數(shù)據(jù)和圖片的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-01-01RestTemplate接口調(diào)用神器常見用法匯總
這篇文章主要介紹了RestTemplate接口調(diào)用神器常見用法匯總,通過案例代碼詳細介紹RestTemplate接口調(diào)用神器常見用法,需要的朋友可以參考下2022-07-07SpringBoot HttpMessageConverter消息轉(zhuǎn)換器的使用詳解
在整個數(shù)據(jù)流轉(zhuǎn)過程中,前端的請求報文轉(zhuǎn)化為Java對象,Java對象轉(zhuǎn)化為響應(yīng)報文,這里就用到了消息轉(zhuǎn)換器HttpMessageConverter2022-06-06ByteArrayOutputStream簡介和使用_動力節(jié)點Java學院整理
ByteArrayOutputStream 是字節(jié)數(shù)組輸出流。它繼承于OutputStream。這篇文章主要介紹了ByteArrayOutputStream簡介和使用,需要的朋友可以參考下2017-05-05