部署DeepSeek模型,进群交流最in玩法!
立即加群
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Redis的key代码能查到,但删不掉,使用keys命令也找不到,崩溃了!!!

Redis的key代码能查到,但删不掉,使用keys命令也找不到,崩溃了!!!

作者头像
烟雨平生
发布2025-03-12 21:31:27
发布2025-03-12 21:31:27
9300
代码可运行
举报
文章被收录于专栏:数字化之路数字化之路
运行总次数:0
代码可运行

先讲原因:redisTemplate对象的key的序列化器是JdkSerializationRedisSerializer,导致redis服务器上的key的名字变了。使用代码中key去删除会失败,查找会找不到。

本例中,代码中的redis Key是"v1:smc:login:info"

Redis服务器上的key的名字变为:

代码语言:javascript
代码运行次数:0
运行
复制
1) "\xac\xed\x00\x05t\x00\x11v1:smc:login:info"

原因知道了,下面来梳理这个问题的排查思路。

背景

uat环境写了个bug,把一个错误的值写到key中。

快速fix后,需要删除这个key。

使用之前的删除接口,提示成功。

再次调试,发现还是旧值,很无语。

直接登录redis服务器删除。

发现没有这个key。

代码语言:javascript
代码运行次数:0
运行
复制
> del v1:smc:login:info
(integer) 0

使用keys命令,返回也是空

代码语言:javascript
代码运行次数:0
运行
复制
> keys v1:smc:login:info
(empty array)

是不是有两个Redis服务器,删除和查找不在同一个? 不是。是同一个。

再次确认下Redis服务器是否相同

决定本地调试一下。本地环境和uat环境用的相同的redis,想查看下这个RedisTemplate配置的是哪个Redis服务器,另外看看这个RedisTemplate是不是有特殊之处?发现这个项目中其它地方只用了StringRedisTemplate。

稳稳的复现:值取到了。仍然是第一次写入的错误值。

这个RedisTemplate配置的host,port,database没有不同。

不死心,又试了这个场景:

key是存在的。与之前的情况完全一致。

代码语言:javascript
代码运行次数:0
运行
复制
[9]> keys *smc*
1) "\xac\xed\x00\x05t\x00\x11v1:smc:login:info"

使用两边*号的查一下,居然找到了。

只是前面被加了些莫名其妙的前缀。

问了下DeepSeek:

该字符串是 Java 序列化二进制数据,头部结构为:

代码语言:javascript
代码运行次数:0
运行
复制
魔数(ACED) + 版本号(0005) + 字符串类型标识(74) + 长度(0011) + 内容(v1:smc:login:info)

该字符串的前面部分 \xac\xed\x00\x05t\x00\x11 并不是标准的 Unicode 编码文本,而是 Java 对象序列化协议的二进制数据头。以下是逐字节解析:

  1. \xac\xed 这是 Java 序列化流的魔数(Magic Number),固定为 0xACED,用于标识这是一个 Java 序列化对象流。
  2. \x00\x05 表示序列化协议的版本号(5),对应 java.io.ObjectStreamConstants.STREAM_VERSION
  3. t 对应 ASCII 字符 t(十六进制 0x74),表示接下来是一个字符串对象(TC_STRING 类型标识符)。
  4. \x00\x11 字符串长度字段,十六进制 0x0011 表示十进制 17,即后续字符串 v1:smc:login:info 的长度(恰好 17 个字符)。

至此找到原因。

解决办法就很简单了。

解决

方法1:使用本项目RedisTemplate对象的delete方法来删除:

用魔法打败魔法。能发起致命攻击的,都是最熟悉你的。

方法2:改下redisKey。

譬如,可以把"v1:smc:login:info"改为"v2:smc:login:info"

是不是可以继续测功能了。

为什么删除接口提示成功了

删除接口在另一个项目中,与这个项目的RedisTemplate的序列化器不同。

没删除掉,为什么提示“deleteKeyCount 1”呢?

看了下代码:

看到原因了不?

此处需要改下一下:

直接使用redisTemplate.delete(key)的返回值就可以了。

复盘

为什么刚开始为什么没想到是Redis序列化器的问题。之前的项目中对RedisTempate进行特殊配置的。没想到这个项目没配,并且老代码中也一直在用。就没有质疑这个部分。

为什么删不掉时,没有想到是这个原因。

项目比较多,有几个项目用了Redis其它的database,也不确定这个是不是也是例外。在这个点上卡的时间有些长。

再加上,删除接口一直反馈“deleteKeyCount 1 ”,然后就卡这了。

心得:代码方面的事,实在没有思路就debug一下,看看具体的数据,没有思路时就先试一试,说不定就找到解决办法了。

所谓:想都是问题,做才可能有答案。

别等万事俱备,才选择开始。

最后,提供一个RedisTempate配置示例,欢迎拍砖:

代码语言:javascript
代码运行次数:0
运行
复制
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setDefaultSerializer(fastJsonRedisSerializer);
    redisTemplate.setConnectionFactory(redisConnectionFactory);
    return redisTemplate;
}

使用这个配置,写到Redis服务器的key就与代码中的相同了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 的数字化之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 再次确认下Redis服务器是否相同
  • 解决
  • 为什么删除接口提示成功了
  • 复盘
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档