[转帖]RedisTemplate写入Redis数据出现无意义乱码前缀\xac\xed\x00\x05

redistemplate,写入,redis,数据,出现,意义,乱码,前缀,xac,xed,x00,x05 · 浏览次数 : 0

小编点评

**乱码前缀的含义:** 乱码前缀 \\xac\\xed\\x00\\x05 代表数据字节数,其中 \\x00 是数据字节数的开始字节, \\x05 是表示“数字 5”的字节。 **原因:** * **ObjectOutputStream序列化魔数:** Java 中的 ObjectOutputStream 使用魔数来表示数据字节数。 \\x00\\x05 的值表示 5 字节。 * **数据字节数不是固定值:** 由于数据字节数可能超过 0xffff 的最大值,因此,\\x00- 是用来表示数据字节数的 시작字节。 * **字符编码:** 在 StringRedisSerializer 中,\\x00- 表示数据字节数的结束符,因为 String 的默认字符集仅支持 ASCII 字符集。 **其他问题:** * 乱码前缀的长度取决于数据字节数的实际值。 * 乱码前缀的格式可能因系统字符集而有所不同。 * 使用 RedisTemplate 进行数据存取时,需要使用 StringRedisSerializer 进行序列化和反序列化。

正文

背景

项目使用Spring的RedisTemplate进行Redis数据存取操作,实际应用中发现Redis中key和value会出现“无意义”乱码前缀\xac\xed\x00\x05t\x00-(样例\xac\xed\x00\x05t\x00-abcd:abc:xxxxxx:passport:associated:key: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:abc:xxxxxx:passport:associated:key:29708的字符数就是45,1个字符1个字节,字节数也是45)。

是不是固定的

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

衍生疑问

为什么显示不一样

为什么有些16进制\x显示,有些ASCII码值对应字符显示?

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

0x20 到 0x7e,都是比较正常的字符,可以显示出来。

参考ASCII码
在这里插入图片描述
在这里插入图片描述

字符长度超长会怎样

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的。现在我们需要排查一个和缓存相关的问题,需要看下Redis中某个缓存值是否存在?

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

总结

  1. 上面使用RedisTemplate的方式是不好的,实际应用中key序列化可以采用StringRedisSerializer。这也是网上大部分文章建议的。
  2. 大部分文章只说了表象原因,没有分析更深入的原因。对从已存在数据中排查问题没有帮助,还是需要自己深究。
文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览91469 人正在系统学习中

与[转帖]RedisTemplate写入Redis数据出现无意义乱码前缀\xac\xed\x00\x05相似的内容:

[转帖]RedisTemplate写入Redis数据出现无意义乱码前缀\xac\xed\x00\x05

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

[转帖]SpringBoot之RedisTemplate操作redis出现\xAC\xED\x00\x05t\x00\x08乱码问题

http://qclog.cn/1118 在SpringBoot中使用RedisTemplate操作redis时,会出现\xAC\xED\x00\x05t\x00\x08这种乱码问题,特别是在使用中文时。原因是因为RedisTemplate中key和value的序列化方式都默认使用了jdk的序列化方

[转帖]Redis key 乱码问题(springboot)

保存到redis中的key 前半段会出现乱码问题 原来配置: @Configuration@EnableCachingpublic class RedisCacheConfig { @Bean public CacheManager cacheManager(RedisTemplate

[转帖]

Linux ubuntu20.04 网络配置(图文教程) 因为我是刚装好的最小系统,所以很多东西都没有,在开始配置之前需要做下准备 环境准备 系统:ubuntu20.04网卡:双网卡 网卡一:供连接互联网使用网卡二:供连接内网使用(看情况,如果一张网卡足够,没必要做第二张网卡) 工具: net-to

[转帖]

https://cloud.tencent.com/developer/article/2168105?areaSource=104001.13&traceId=zcVNsKTUApF9rNJSkcCbB 前言 Redis作为高性能的内存数据库,在大数据量的情况下也会遇到性能瓶颈,日常开发中只有时刻

[转帖]ISV 、OSV、 SIG 概念

ISV 、OSV、 SIG 概念 2022-10-14 12:29530原创大杂烩 本文链接:https://www.cndba.cn/dave/article/108699 1. ISV: Independent Software Vendors “独立软件开发商”,特指专门从事软件的开发、生产、

[转帖]Redis 7 参数 修改 说明

2022-06-16 14:491800原创Redis 本文链接:https://www.cndba.cn/dave/article/108066 在之前的博客我们介绍了Redis 7 的安装和配置,如下: Linux 7.8 平台 Redis 7 安装并配置开机自启动 操作手册https://ww

[转帖]HTTPS中间人攻击原理

https://www.zhihu.com/people/bei-ji-85/posts 背景 前一段时间,公司北京地区上线了一个HTTPS防火墙,用来监听HTTPS流量。防火墙上线之前,邮件通知给管理层,我从我老大那里听说这个事情的时候,说这个有风险,然后意外地发现,很多人原来都不知道HTTPS防

[转帖]关于字节序(大小端)的一点想法

https://www.zhihu.com/people/bei-ji-85/posts 今天在一个技术群里有人问起来了,当时有一些讨论(不完全都是我个人的观点),整理一下: 为什么网络字节序(多数情况下)是大端? 早年设备的缓存很小,先接收高字节能快速的判断报文信息:包长度(需要准备多大缓存)、地

[转帖]awk提取某一行某一列的数据

https://www.jianshu.com/p/dbcb7fe2da56 1、提取文件中第1列数据 awk '{print $1}' filename > out.txt 2、提取前2列的文件 awk `{print $1,$2}' filename > out.txt 3、打印完第一列,然后打