Spring整合redis的key时出现\xac\xed\x00\x05t\前缀问题

news2024/12/23 10:10:08
@Autowired
    RedisTemplate redisTemplate;

User user=new User(5,"tomhs","tttt");
        ValueOperations opsForValue = redisTemplate.opsForValue();
        //存放key,
        opsForValue.set("user"+user.getId(),user);

        //读取数据;
        System.out.println(opsForValue.get("user" + user.getId()));

背景
项目使用Spring的RedisTemplate进行Redis数据存取操作,实际应用中发现Redis中key和value会出现“无意义”乱码前缀\xac\xed\x00\x05t\x00-(样例\xac\xed\x00\x05t\x00-abcd🔤xxxxxx:passport:associated🔑29708)。

这个乱码前缀是怎么产生的呢?有什么含义?是不是固定的?带着这三个问题,我们一探究竟。

疑问探究
怎么产生的
org.springframework.data.redis.core.RedisTemplate实例化需要序列化和反序列化组件,如果我们不指定,默认使用org.springframework.data.redis.serializer.JdkSerializationRedisSerializer进行序列化,而JdkSerializationRedisSerializer最终使用的是Java原生java.io.ObjectOutputStream.ObjectOutputStream(OutputStream)进行序列化。

这个乱码前缀就是ObjectOutputStream进行序列化时添加的。
有什么含义
\x对应0x

\xac\xed对应是0xaced,是ObjectOutputStream的序列化魔数(见java.io.ObjectStreamConstants.STREAM_MAGIC)。

\x00\x05对应是5,是ObjectOutputStream的序列化版本(见java.io.ObjectStreamConstants.STREAM_VERSION)。

这里引出一个小问题:为什么是\x00\x05而不是\x05?

因为上面2个值write时采用的是short,占2个字节。

样例乱码\x05后面有个t,不是很明显。t是转化后的ASCII码值对应字符,对应16进制是0x74,是ObjectOutputStream分配给String类型标记(见java.io.ObjectStreamConstants.TC_STRING)。

\x00-是有\x00和-组成的,是一起的,表示数据的字节数。-是转化后的ASCII码值对应字符,对应16进制是0x2d(10进制是45,样例abcd🔤xxxxxx:passport:associated🔑29708的字符数就是45,1个字符1个字节,字节数也是45)。

是不是固定的
由上面的描述可知,乱码前缀中\xac\xed\x00\x05是固定的,t在String类型情况是不变的,后面2个位(样例\x00-)是数据的字节数,是随key动态变化的。

衍生疑问
为什么显示不一样
为什么有些16进制\x显示,有些ASCII码值对应字符显示?

结合ASCII码对应的字符表,推测和显示系统能支持的字符集有关。

0x20 到 0x7e,都是比较正常的字符,可以显示出来。
字符长度超长会怎样
2个字节表示数据字节数,即最大0xffff,10进制为65535,key长度超过后会怎么样?

经试验,

key长度65535时,乱码为\xac\xed\x00\x05t\xff\xff

key长度65545时,乱码为\xac\xed\x00\x05|\x00\x00\x00\x00\x00\x01\x00\x09

t上面说过,是转化后的ASCII码值对应字符,对应16进制是0x74,是ObjectOutputStream分配给String类型标记(见java.io.ObjectStreamConstants.TC_STRING)。

|也是转化后的ASCII码值对应字符,对应16进制是0x7c,是ObjectOutputStream分配给长字符串类型标记(见java.io.ObjectStreamConstants.TC_LONGSTRING)。

同时,表示数据字节数的数值位数也变成了8位bigint。

综上,不用担心key长度越界。
使用全局化RedisTemplate配置即可

package com.yh.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author by 张晨光
 * @date 2023/11/13 12:06
 */
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        //使用jackson进行序列化
        Jackson2JsonRedisSerializer jsonRedisSerializer =
                new Jackson2JsonRedisSerializer(Object.class);
        //规定序列化规则
        ObjectMapper objectMapper = new ObjectMapper();
        /**
         * 第一个参数指的是序列化的域,ALL指的是字段、get和set方法、构造方法
         * 第二个参数指的是序列化哪些访问修饰符,默认是public,ANY指任何访问修饰符
         */
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //指定序列化输入的类型,类必须是非final修饰的类
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jsonRedisSerializer.setObjectMapper(objectMapper);
        //序列化key value
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

应用
通过上面的探究,我们知道了“无意义”乱码前缀的含义。

如果我们新接手一个系统,它是这样使用RedisTemplate的。现在我们需要排查一个和缓存相关的问题,需要看下Redis中某个缓存值是否存在?

我们梳理业务组合出key,通过redis-cli尝试get key是获取不到结果的,此时我们可以根据上面规则自己生成“乱码前缀”,通过get “乱码前缀”+key 就可以判断缓存值是否存在了。
在这里插入图片描述

总结
上面使用RedisTemplate的方式是不好的,实际应用中key序列化可以采用StringRedisSerializer。这也是网上大部分文章建议的。
大部分文章只说了表象原因,没有分析更深入的原因。对从已存在数据中排查问题没有帮助,还是需要自己深究。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1202224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

只有开源才能拯救AI

导语 | 随着 AI 技术的蓬勃发展&#xff0c;大模型的开源化正成为人工智能领域的新潮流&#xff0c;但同时引发的伦理和安全风险也饱受大家关注&#xff0c;如何把握平衡其中的尺度成为开源的一大难题。我们又应该如何有效进行开源治理&#xff1f;未来将走向何方&#xff1f;今…

振动异响振动案例 | 宝马 320D M 运动型 xDrive 旅行版(右舵) | 转向柱发出敲击声

顾客描述 客户报告说&#xff0c;来回摇动方向盘时&#xff0c;可以通过转向柱感觉到和听到敲击声。虽然症状已经存在了大约六个月&#xff0c;但它不会影响车辆的性能或操控性。我们的客户还报告了在低速驶过减速带时&#xff0c;悬架会发出间歇性的敲击声。技术描述 …

中小企业数字化转型进程加速,CRM系统前景如何?

自疫情不断反复之后&#xff0c;中小企业数字化转型进程开始加速。作为当下最热门的企业级应用&#xff0c;CRM客户管理系统的前景还是被看好的。相比于美国企业CRM系统7成的使用率&#xff0c;中国的CRM市场还有很大的发展空间。下面来详细说说&#xff0c;CRM系统的前景如何&…

研究生做实验找不到数据集咋办?

做实验找不到数据集咋办?这是很多研究者和开发者都会遇到的问题。数据集是实验的基础,没有合适的数据集,就无法验证模型的性能和效果。那么,有没有什么方法可以快速地找到我们需要的数据集呢?本文将介绍4个常用的数据集搜索平台,希望能够帮助大家解决这个难题。下面以室内…

[EFI]技嘉 Z490 VISION G i5-10500 电脑 Hackintosh 黑苹果引导文件

硬件配置 硬件型号驱动情况主板技嘉 Z490 VISION G CLPC controller Z490芯片组&#xff09;处理器英特尔 Core i5-10500 3.10GHz 六核已驱动内存16GB&#xff08; 威到DDR42655MHz8GBx 2〕已驱动硬盘SSDSC2BB150G7R (150 GB/ 国态硬盘&#xff09;已驱动显卡AMD Radeon RX 58…

【陈老板赠书活动 - 18期】- 计算机考研精炼1000题

陈老老老板&#x1f9b8; &#x1f468;‍&#x1f4bb;本文专栏&#xff1a;赠书活动专栏&#xff08;为大家争取的福利&#xff0c;免费送书&#xff09; &#x1f468;‍&#x1f4bb;本文简述&#xff1a;生活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f468;‍&am…

【沐风老师】3dMax一键多边形窗插件PolyWindow使用教程

3dMax一键多边形窗插件使用教程 3dMax一键多边形窗插件PolyWindow&#xff0c;将选择的多边形面一键转化为窗模型。你可以通过编辑多边形的线框&#xff08;边&#xff09;来定义窗子的分格形状&#xff0c;这款插件可以大大提高艺术家建筑建模、室内建模制作窗子的速度。 可适…

flask框架报错解决方法

1、报错 jinja2.exceptions.TemplateNotFound 解决方法&#xff1a;报错jinja2.exceptions.TemplateNotFound&#xff0c;template没找到&#xff0c;由于我之前直接将.html文件和.py文件直接放在同一目录下&#xff0c;经了解&#xff0c;需要新增一个 templates目录&#xff…

继承和多态_Java零基础手把手保姆级教程(超详细)

文章目录 Java零基础手把手保姆级教程_继承和多态&#xff08;超详细&#xff09;1. 继承1.1 继承的实现&#xff08;掌握&#xff09;1.2 继承的好处和弊端&#xff08;理解&#xff09; 2. 继承中的成员访问特点2.1 继承中变量的访问特点&#xff08;掌握&#xff09;2.2 sup…

Git分支与Git标签详解

目录 前言 一、Git分支&#xff08;Branch&#xff09; 1.分支的概念 2.分支的常用操作 3.Git 分支管理 二、Git标签&#xff08;Tag&#xff09; 1.标签的概念 2.标签的类型 3.标签的常用操作 4.Git标签管理 前言 在软件开发过程中&#xff0c;版本管理是非常重要的一…

C++11『基础新特性』

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f383;操作环境&#xff1a; Visual Studio 2022 版本 17.6.5 文章目录 &#x1f307;前言&#x1f3d9;️正文1.C11 简介1.1.起源1.2.主要更新 2.列表初始化2.1.对于内置类型2.2.对于自定义…

频域分析实践介绍

频域分析实践介绍 此示例说明如何执行和解释基本频域信号分析。该示例讨论使用信号的频域表示相对于时域表示的优势&#xff0c;并使用仿真数据和真实数据说明基本概念。该示例回答一些基本问题&#xff0c;例如&#xff1a;FFT 的幅值和相位的含义是什么&#xff1f;我的信号是…

实战 | 基于卷积神经网络的蘑菇识别微信小程序

一个不知名大学生&#xff0c;江湖人称菜狗 original author: Jacky Li Email : 3435673055qq.com Time of completion&#xff1a;2023.11.13 Last edited: 2023.11.13 导读&#xff1a;其实没啥难的&#xff0c;主要是随手搞了就发出来把&#xff0c;太久没有水过帖子了&…

学生五科成绩统计

随机生成10名学生姓名(包括自己)和五科成绩&#xff0c;将数据存入*.csv&#xff0c;读取保存的*.csv文本数据计算每个学生总分和平均分&#xff0c;并存入*.csv文本&#xff1b;打印总分排名前三学生信息&#xff1b;查找10学生各科最高最低分、中位分、平均分。 (笔记模板由p…

2023CCPC深圳流水账

在高铁上无聊&#xff0c;写一个这三天的小总结吧 不知道该写点啥&#xff0c;就想到什么写什么了 铁了&#xff0c;也在意料之中&#xff0c;概率期望和字符串一直是弱点&#xff0c;考前也在赌不会考这两个结果两个都考了&#xff0c;赫赫&#xff0c;看来在杭州站之前得好…

无代码业务自动化工具Activepieces

什么是 Activepieces &#xff1f; Activepieces 是一款工作流程自动化软件&#xff0c;可以帮助您自动化所有重要流程&#xff0c;例如市场、销售、营销等。您可以集成其他有用的应用程序并更有效地管理您的业务。无需编码&#xff0c;是 Zapier 的绝佳替代品。 Activepieces …

深耕智慧物流夯实竞争优势,极智嘉(Geek+)斩获多项大奖

全球仓储机器人引领者极智嘉(Geek)&#xff0c;一直以来致力于为仓储与制造场景提供高效柔性的智能物流解决方案&#xff0c;强劲的发展实力备受认可。而近段时间&#xff0c;极智嘉更是频频传来好消息&#xff0c;不仅斩获了英国机器人与自动化仓储创新大奖&#xff0c;获评胡…

什么是Vue.js的计算属性(computed properties)?与方法(methods)有什么不同?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

Python高级语法---Python内存管理机制

文章目录 1. 内存管理基础引用计数2. 垃圾回收机制垃圾回收3. 使用weakref处理循环引用weakref模块总结Python是一种高级编程语言,其内存管理机制高效且用户友好。这篇文章将详细介绍Python的内存管理基础、垃圾回收机制,以及如何使用weakref模块处理循环引用。我们将通过简单…

基于C#开发的任天堂 Switch 开源模拟器

今天给大家推荐一款基于C#开发的任天堂 Switch 开源模拟器&#xff0c;可方便开发人员来测试游戏&#xff0c;也用于娱乐。 01 项目简介 Ryujinx 是一个开源的任天堂 Switch 模拟器&#xff0c;可以在 PC 上模拟运行 Switch 游戏。采用C#开发&#xff0c;基于 .NET Core技术框…