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

@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。这也是网上大部分文章建议的。
大部分文章只说了表象原因,没有分析更深入的原因。对从已存在数据中排查问题没有帮助,还是需要自己深究。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java DataSize存储容量单位规范化设置

之前的文章 java Duration格式规范化 自定义时间单位类型我们讲述了 Duration 这种jdk单位规范 其实我们还有一个单位 DataSize 我们这里属性类中 加入这个 DataSize的一个属性 然后设置他的 get set函数 然后 toString中加上他的输出 方便我们去看 这个类型是用来设置存储容…

预后模型+实验生信思路,新颖可重复发文空间大

今天给同学们分享一篇生信文章“Novel Implication of the Basement Membrane for Breast Cancer Outcome and Immune Infiltration”&#xff0c;这篇文章发表在Int J Biol Sci期刊上&#xff0c;影响因子为3.5。 结果解读&#xff1a; 建立骨髓评分的预后骨髓基因选择策略 …

Linux Mint 21.3 将搭载 Cinnamon 6.0 和实验性 Wayland 支持

导读Wayland 会话可能在 Linux Mint 23 系列中成为默认选项&#xff0c;预计将在 2026 年实现。 Linux Mint 项目今天在他们的每月新闻通讯中 宣布&#xff0c;他们已经开始着手在未来的 Linux Mint 发行版中实施 Wayland 会话&#xff0c;最初将在 Linux Mint 21.3 中提供。 …

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;这是一个最好的时代。 《全球数字经济白皮书&#xff08;2023年&#xff09;》介绍&#xff0c;2016年-2022年&#xff0c;中国数字经济年均复合增长率为14.2%&#xff0c;数字经济发展增速和规模兼具。随着数字基础实施持续夯实、数字应用不…

接口开放太麻烦?试试阿里云API网关吧

前言 我在多方合作时&#xff0c;系统间的交互是怎么做的&#xff1f;这篇文章中写过一些多方合作时接口的调用规则和例子&#xff0c;然而&#xff0c;接口开放所涉及的安全、权限、监控、流量控制等问题&#xff0c;可不是简简单单就可以解决的&#xff0c;这一般需要专业的…

红队系列-shellcode AV evasion免杀合集

shellcode免杀 一些概念shellcode EDR 了解国内360全家桶360核晶引擎 火绒腾讯电脑管家安全狗金山毒霸瑞星 国外Windwos DefenerKaspersky 卡巴斯基ESET Nod32NortonMcAfeeAVASTAVG科摩多火眼诺顿Symantec小红伞 AV检测方式分类静态扫描引擎特征码扫描识别文件效验和法静态免杀…

媒体软文投放的流程与媒体平台的选择

海内外媒体软文&#xff1a;助力信息传播与品牌建设 在当今数字化时代&#xff0c;企业如何在庞大的信息海洋中脱颖而出&#xff0c;成为品牌建设的领军者&#xff1f;媒体软文投放无疑是一项强大的策略&#xff0c;通过选择合适的平台&#xff0c;精准投放&#xff0c;可以实…

大洋钻探系列之二IODP 342航次是干什么的?(上)

本文简单介绍一下大洋钻探IODP 342航次&#xff0c;从中&#xff0c;我们一窥大洋钻探航次的风采。 IODP342的航次报告在网络上可以下载&#xff0c;英文名字叫《Integrated Ocean Drilling ProgramExpedition 342 Preliminary Report》&#xff0c;航次研究的主要内容是纽芬兰…

学习c#的第九天

C# 可空类型&#xff08;Nullable&#xff09; C# 可空类型&#xff08;Nullable&#xff09; 可空类型允许我们在值类型中包含 null 值&#xff0c;这在处理数据库查询结果或需要表示缺失值的情况时非常有用。 声明一个可空类型的语法如下&#xff1a; < data_type>…

【Python Opencv】图片与视频的操作

文章目录 前言一、opencv图片1.1 读取图像1.2 显示图像1.3 写入图像1.4 示例代码 二、Opencv视频2.1 从相机捕获视频获取摄像头一帧一帧读取显示图片VideoCapture 中的get和set函数示例代码 2.2 从文件播放视频示例代码 2.3 保存视频示例代码 总结 前言 在计算机视觉和图像处理…

蓝桥杯 选择排序

选择排序的思想 选择排序的思想和冒泡排序类似&#xff0c;是每次找出最大的然后直接放到右边对应位置&#xff0c;然后将最 右边这个确定下来&#xff08;而不是一个一个地交换过去&#xff09;。 再来确定第二大的&#xff0c;再确定第三大的… 对于数组a[]&#xff0c;具体…

50个值得关注的生成式AI初创企业【2023】

在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 生成式AI初创公司已成为科技界最新、最强大的参与者&#xff0c;它们利用自然语言处理、机器学习和其他形式的人工智能为各种业务用例生成…

总结MYSQL中VHARCHAR和TEXT

前几天在设计表结构时&#xff0c;针对表中的一个字段使用text还是使用varchar是受到了开发同学的挑战。本篇文章对text和varchar的区别做个总结。 VHARCHAR和TEXT对比 char(n)varchar(n)中括号中n代表字符的个数&#xff0c;并不代表字节个数&#xff0c;所以当使用了中文的…

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

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

LCA

定义 最近公共祖先简称 LCA&#xff08;Lowest Common Ancestor&#xff09;。两个节点的最近公共祖先&#xff0c;就是这两个点的公共祖先里面&#xff0c;离根最远的那个。 性质 如果 不为 的祖先并且 不为 的祖先&#xff0c;那么 分别处于 的两棵不同子树中&#…

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

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

同为科技(TOWE)主副控智能自动断电桌面PDU插排

在这个快节奏的现代社会&#xff0c;我们越来越需要智能化的产品来帮助我们提高生活质量和工作效率&#xff0c;同时&#xff0c;为各种家用电器及电子设备充电成为不少消费者新的痛点。桌面插排如何高效、安全地管理这些设备&#xff0c;成为了一个亟待解决的问题。同为科技&a…

CopyOnWriteArrayList内存占用过多

目录 一、CopyOnWriteArrayList二、CopyOnWriteArrayList的适用场景三、CopyOnWriteArrayList内存占用过多的解决方法四、CopyOnWriteArrayList.add()源码分析 大家好&#xff0c;我是哪吒。 一、CopyOnWriteArrayList CopyOnWriteArrayList是Java中的一个线程安全的ArrayLis…

负债1320万美元的【思宏集团/Neo-Concep】申请900万美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于香港的思宏集团Neo-Concept International Group Holdings Limited(简称&#xff1a;思宏集团&#xff09;近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c…