Spring Boot项目中使用RedisTemplate.delete() 删除指定key失败 的解决办法

RedisTemplate常用方法总结(参考官方文档2.6.2) title: RedisTemplate常用方法总结(参考官方文档2.6.2) date: 2022-02-27 03:40:27 tags: Redis categories: Redis cover: https://cover.png feature: false 1. 简介 RedisTemplate 是 Spring Data Redis 提供给用户的最高级的抽象客户端,用户可直接通过 RedisTemplate进行多种操作。 1.1 类继承关系 public class RedisTem. 阅读详情
AI摘要

在SpringBoot项目中,使用自定义序列化机制后,原生RedisTemplate.delete()方法删除key时,虽然提示成功,但实际key未从Redis中删除。此问题源于不同序列化方式的不兼容。

 

问题概述

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

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 服务器上咯。

 

 

 

 

 


 好了,关于 Spring Boot项目中使用RedisTemplate.delete() 删除指定key成功,但在Redis中并未删除 的解决办法  就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。 
歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。


作       者:华    仔
联系作者:who.seek.me@java98k.vip
来        源:优快云 (Chinese Software Developer Network)
原        文:https://blog.youkuaiyun.com/Hello_World_QWP/article/details/85763286
版权声明:本文为博主原创文章,请在转载时务必注明博文出处!
Spring Boot Redis客户端选型指南:Jedis、Lettuce、RedisTemplate与Redisson实战解析 在分布式系统和高并发应用中,缓存是提升性能、降低数据库负载的核心技术。其原理是将热点数据存储在内存中,通过键值对提供高速访问,从而减少对后端持久化存储的I/O压力。Redis作为高性能的内存数据存储,凭借其丰富的数据结构和原子操作,成为实现分布式缓存、会话共享和分布式协调的关键组件。在Java生态中,Spring Boot通过集成多种Redis客户端,为开发者提供了灵活的选择。Jedis作为老牌同步阻塞客户端,适合简单场景;Lettuce基于Netty实现了非阻塞I/O和响应式编程,是高并发场景的默认选择; 阅读详情

相关推荐

Redis Key乱码排查与修复:Java序列化与RedisTemplate配置

在Java技术栈的缓存实践中,序列化是衔接业务对象与存储介质的关键技术。当Redis中的key出现如\xac\xed开头的神秘十六进制前缀时,往往并非数据损坏,而是JDK原生序列化机制在背后作祟。Java序列化协议通过固定魔数标识对象流,Spring Boot中默认的RedisTemplate若未显式指定序列化器,会采用JdkSerializationRedisSerializer,导致key以二进制形态落库。清晰理解序列化原理,合理选配StringRedisSerializer与GenericJackso

weixin_34195364的博客 255

redisTemplate.delete删除失败

线上发现有缓存清楚失败的情况,线下模拟执行了下,发现redisTemplate.delete(key)返回false,网上查了下,说可能是set和delete用的不一致导致,比如set的时候用的,RedisTemplate<String, String>,而delete的时候用的RedisTemplate,确认在确定两边使用一致后,在delete前get了一下数据,发现是能获取到的。 最终找到的原因是,两边使用序列化不一致导致的,set的时候,使用的StringRedisS...

记录 1万+

Spring Boot Redis入门必看:opsForValue()核心API、原子性与序列化坑全解析

在Spring Boot项目中,Redis是最常用的缓存中间件之一,而RedisTemplate作为数据访问入口,其opsForValue()方法承载着字符串类型最核心的读写、计数与分布式锁操作。理解ValueOperations的底层原理,掌握setIfAbsent、increment等原子方法的语义边界,是避免并发超卖、缓存穿透、锁误删等生产事故的关键。本文从Redis单线程命令模型出发,梳理set/get、批量操作、分布式锁实现、序列化配置等高频要点,并结合TTL设计和接口幂等场景,帮助后端开发者构建

weixin_30399155的博客 266

每日一坑:SpringBoot中引入RedisTemplate后调用delete方法失效?大坑比

如题,如果你跟我一样,在springboot的Controlle层调用delete的时候初心大意,使用的是StringRedisTemplate对Redis中的key进行的set操作,然后后使用RedisTemplate调用delete操作删除Redis中的key,出现空异常。你需要做的: (1)检查你在调用存储Key的时候,set方法是由哪个对象发起的?你是用RedisTemplate还是用的StringRedisTemplate调用的set的。 (2)如果是StringRedisTemplate调用的s

qq_44918802的博客 3950

告别开发“坐牢”:Spring Boot集成Redis缓存实战与多练辅助方法论

缓存是提升系统性能、降低数据库负载的核心技术之一,其原理是将高频访问的数据存储在更快的介质中,减少对后端数据源的直接访问。在分布式系统中,缓存技术对于应对高并发场景、保障系统响应速度具有关键价值,广泛应用于电商秒杀、社交动态、内容推荐等场景。然而,在实际集成缓存时,开发者常因环境配置、缓存穿透、数据一致性等问题陷入调试困境,即所谓的“坐牢”状态。本文以Spring Boot集成Redis为具体案例,系统性地演示了如何通过**环境辅助**与**任务拆解**的方法论,将复杂的技术集成过程工程化,从搭建可复现的D

weixin_30655569的博客 447

SpringBoot中RedisTemplate操作List数据结构:从基础API到实战场景详解

缓存是提升应用性能的核心技术之一,其原理是将高频访问的数据存储在内存中,以减少对数据库的直接访问,从而显著降低响应延迟并提升系统吞吐量。在Java生态中,SpringBoot通过Spring Data Redis提供了与Redis集成的标准化方案,其中RedisTemplate作为核心操作模板,封装了丰富的数据结构操作。List作为Redis的关键数据结构之一,凭借其有序、可重复及支持两端操作的特性,在工程实践中具有独特的技术价值。它非常适合需要维护顺序或实现队列/栈模型的场景,例如记录用户最近操作日志、实

weixin_30321449的博客 328

RedisTemplate 快速使用入门 与 操作 Redis 5 种数据类型、事务

目录 RedisTemplate 概述 与 redis 配置 RedisTemplate 使用演示 字符串(String) 列表(List) 哈希(Hash) 集合(Set) 有序集合(sorted set) RedisTemplate 概述 与 redis 配置 1、Redis 是一个缓存、消息代理和功能丰富的键值存储。Spring Boot 为 Lettuce 和 Jedis...

蚩尤后裔-汪茂雄 1万+

Spring Data RedisTemplate的delete方法实现分析及源代码示例

然后,我们定义了一个deleteKey方法,该方法接收一个key作为参数,并使用redisTemplate的delete方法来删除指定的key。总结起来,RedisTemplate的delete方法通过调用RedisConnection的del方法来执行删除操作,并根据删除的结果返回相应的布尔值。从上述代码中可以看到,delete方法接收一个泛型参数K,表示要删除的key的类型。最后,execute方法会对删除操作的结果进行判断,如果返回值大于0,则表示删除成功,返回true;如果有任何问题,欢迎提出。

PixelLoom的博客 707

Spring Boot如何集成Redis

本文介绍了在Spring Boot项目中集成Redis的详细步骤。首先说明开发环境要求(IDEA 2026.1、JDK 17等),然后演示如何创建Spring Boot项目并选择相关配置。重点内容包括:引入Redis依赖和连接池依赖,配置Maven项目文件;修改YAML配置文件设置Redis连接参数;创建RedisConfig配置类解决序列化问题,通过@Bean注解配置RedisTemplate,使用GenericJackson2JsonRedisSerializer实现键值对的序列化。文中配有详细截图和代

城南蝈蝈 1434

【SpringBoot】34、SpringBoot整合Redis实现序列化存储Java对象

前面我们已经介绍过【SpringBoot】十七、SpringBoot 中整合 Redis,我们可以看出,在 SpringBoot 对 Redis 做了一系列的自动装配,使用还是非常方便的 一、背景 1、思考‘ 通过我们前面的学习,我们已经可以往 Redis 中存入字符串,那么我们要往 Redis 中存入 Java 对象该怎么办呢? 2、方案 我们可以将 Java 对象转化为 JSON 对象,然后转为 JSON 字符串,存入 Redis,那么我们从 Redis 中取出该数据的时候,我们也只能取出字符串,并转

JACKAL 22万+

苍穹外卖-day05(SpringBoot+SSM的企业级Java项目实战)

Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件。Redis中文网key-value结构存储:基于内存存储,读写性能高适合存储热点数据(热点商品、资讯、新闻)企业应用广泛Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。它存储的value类型比较丰富,也被称为结构化的NoSql数据库。NoSql(Not Only SQL),不仅仅是SQL,泛指。

weixin_45210565的博客 993

记一次Redis批量删除Key问题

记一次Redis批量删除Key问题 前言 最近在项目中使用redis时发现一个问题,批量删除的时候删除不了。 代码如下 // redis配置 @Bean public RedisTemplate redisTemplate(RedisConnectionFactory factory) { RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(factory); re

席儒空间 1181

Spring Boot商城项目gpmall部署实战:从目录结构到避坑指南

Java Web商城是许多开发者在毕业设计或工程入门时都会接触的经典项目形态。它通常以Spring Boot为核心框架,结合MySQL、Redis、Nginx等基础设施,实现商品、购物车、订单和后台管理等功能闭环。理解这类项目的目录结构、配置优先级和部署顺序,是快速掌握电商系统开发的关键。通过分析一份完整的gpmall资料包,可以理清前后端分离架构下,数据库导入、后端服务启动、前端资源映射之间的关系;同时掌握登录权限、商品缓存、订单防超卖等常见业务逻辑。以gpmall为例,梳理从环境准备到实际运行的全过程,

weixin_33980459的博客 559

Spring Boot项目CSRF防护实战:从原理到配置详解

在Web应用开发中,安全防护是保障系统稳定运行的重要环节。CSRF(跨站请求伪造)攻击是一种利用用户对网站的信任,通过伪造请求执行非授权操作的安全威胁。其防御原理主要基于同步令牌模式,通过在请求中嵌入不可预测的令牌来验证请求的合法性。Spring Security作为Java生态中广泛使用的安全框架,提供了内置的CSRF防护机制,通过配置可有效抵御此类攻击。在Spring Boot项目中,开发者需要正确配置CSRF防护,特别是在处理表单提交和AJAX请求时,确保令牌的正确传递。本文结合Spring Boot

weixin_30654419的博客 459

从调节阀到步进电机:图解位置型PID与增量式PID的核心区别

本文深入解析了位置型PID与增量式PID的核心区别。通过调节阀和步进电机的实例,阐明位置式PID输出绝对位置,适用于直接控制执行机构;而增量式PID输出位置变化量,天然支持无扰动切换,更适合步进电机等场景。文章重点剖析了增量式PID在系统安全与平滑切换方面的关键优势。

weixin_29051811的博客 356

金融波动预测:GARCH模型实战解析与ARIMA对比

本文深入解析GARCH模型在金融波动预测中的实战应用,并与传统ARIMA模型进行对比。通过沪深300指数日收益率数据的案例分析,展示GARCH模型如何有效捕捉波动聚集效应,提升极端波动预测准确率。文章包含Python代码实现、参数解读及模型选择指南,为量化交易者提供实用的波动率建模解决方案。

weixin_29098367的博客 189

代码删Key无报错,缓存永远删不掉!RedisTemplate默认JDK序列化带前缀乱码,线上缓存操作失效故障复盘

初级开发:能注入、能读写、不报错就是没问题。中高级开发:默认配置大多是生产隐患,看不见的序列化、底层差异,才是线上最恐怖的BUG。看似简单的Redis缓存操作,藏着无数人踩过的隐形大坑。

weixin_43144460的博客 338

保姆级教程:用Python工具搞定MTK手机分区表(PGPT)备份与线刷引导文件生成

本文提供了一份详细的Python工具链教程,帮助用户备份MTK手机的PGPT分区表并生成线刷引导文件。内容涵盖环境配置、分区表解析、备份流程、线刷文件生成及常见问题排查,特别适合安卓玩机爱好者和开发者。通过本指南,读者可掌握MTK芯片设备的底层分区操作技术,实现安全高效的分区备份与恢复。

weixin_30394669的博客 188

Spring Boot与Redis分布式缓存面试全解析

分布式缓存是解决高并发场景下系统性能瓶颈的关键技术,其核心原理是通过内存存储高频访问数据减少数据库压力。Redis作为主流内存数据库,支持丰富的数据结构如String、Hash、List等,配合Spring Boot的缓存抽象能实现多级缓存架构。在工程实践中,需要解决缓存穿透、雪崩、击穿等典型问题,常用方案包括布隆过滤器、差异化过期时间和分布式锁。互联网大厂面试常考察Spring Boot自动配置机制与Redis的深度整合,涉及@Cacheable注解原理、Redisson分布式锁实现等实战场景。掌握这些技

weixin_30550081的博客 360

Linux下科大讯飞离线语音识别SDK从下载到实战(附常见问题解决)

本文详细介绍了在Linux系统下,如何从科大讯飞开放平台获取离线语音识别SDK,完成环境准备、编译部署到实战开发的完整流程。文章重点解析了SDK目录结构、语法词典定制、示例代码修改,并针对开发中常见的“词典加载失败”、音频格式、交叉编译及性能优化等问题提供了深度解决方案,助力嵌入式与IoT开发者快速实现稳定可靠的离线命令识别功能。

honey的博客 1237

folium离线地图实战:从下载到部署的完整指南

本文提供了一份完整的folium离线地图实战指南。针对网络不稳定或内网环境下的地图应用需求,详细讲解了如何下载离线地图瓦片数据,并通过两种核心方法(直接替换URL与创建TileLayer)将其集成到folium中。文章还涵盖了部署优化、边界处理及资源本地化等关键步骤,帮助你构建完全脱离网络依赖的交互式地图应用。

weixin_29061041的博客 273

Spring Boot微服务电商项目实战:从环境搭建到K8s部署

微服务架构作为现代分布式系统设计的核心模式,通过将单一应用拆分为多个松耦合的小型服务来实现业务解耦和技术异构。其核心原理基于领域驱动设计和服务治理,利用Spring Cloud生态中的服务注册发现、配置中心和API网关等组件构建高可用系统。这种架构的技术价值在于提升开发效率、增强系统弹性和支持持续交付。在电商、金融等高频并发场景中,微服务能够有效应对业务复杂度。以Spring Boot和Docker为代表的容器化技术,结合MySQL、Redis等数据存储方案,为构建企业级应用提供了完整解决方案。通过项目驱动

weixin_30443731的博客 593

Docker新手必看:解决‘Unable to find image’错误的完整指南

本文针对Docker新手常见的‘Unable to find image’错误,提供了完整的排查与解决指南。文章深入剖析了权限不足、网络连接失败、Docker服务未运行等核心原因,并给出了将用户加入docker组、配置镜像加速器等实用解决方案,帮助读者彻底理解并解决镜像拉取问题。

weixin_29230901的博客 241
上一篇: Spring Cloud 基本理论概述
下一篇: rejected - non-fast-forward 的解决办法
TechBro华仔
TechBro华仔 优质创作者: Java技术领域 优质创作者: Java技术领域 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄11年 5万+粉丝 430原创
评论 33
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TechBro华仔

日拱一卒无有尽,功不唐捐终入海

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值