当前位置: 首页 > news >正文

redis序列化

        测试环境的接口没有返回值,经过查询发现是直接从redis中读取的数据,由于不清楚是通过什么方式写入的redis(没仔细想办法找到写入的代码),所以查询了开发环境的redis key,发现有数据,就想直接将开发环境的key 和value手动写入到测试环境。手动复制的过程中发现value的中文都是些编码过的16进制的符号,然后在复制到测试环境后,测试环境接口报错,解析对象异常。估计是序列化引起的问题,虽然value只能看到值,但是我记得好像有些会存@class之类的,暂时不清楚,只有回头查找程序是在哪里写入redis的,直接对该key idea中全局查找,就找到了写入的接口,接口逻辑,查询数据库,然后写入redis,手动在数据库添加测试数据,然后调用该接口,成功写入redis。

总结:
  • 1.遇到问题,不能总想着偷懒的方式解决,多思考一步,或许很容易就能找到更合适的方法

  • 2.先将直观的方式和可行的方案都罗列出来,评估选定一个合适的方案。多思考,思考清楚了在动手,而不是动手后发现不行,再思考一下,发现有更简单的方式。

为什么使用redis-cli查询value,中文是16进制数据

原因解析
1.Redis存储的本质

Redis存储的是二进制安全的字节序列(byte[]),不关心内容编码(UTF-8,GBC等)

  • 程序写入时,序列化器(如StringRedisSerializer)会将字符串转为UTF-8编码的字节数组存入redis.

  • 中文字符在UTF-8中通常占3个字节(如“中”->\xE4\xB8\xAD)

2.redis-cli的默认行为
  • 默认以ASCLL安全模式显示数据:非ASCII字符(如中文)会被转义为\xXX形式(每个字节的十六进制值)

  • 这是为了保护终端显示安全,避免二进制数据(如图片)直接输出到终端导致乱码或控制符误触发。

3.应用程序的行为
  • 程序读取数据后,会用相同的序列化器(如UTF-8解码)将字节数组还原为字符串,因此中文正常显示。

若已进入redis-cli交互界面,则在查询命令前加 RAW

#在get命令前加 RAW
​
127.0.0.1:6379> SET your_key "你好"  # 写入测试数据
127.0.0.1:6379> GET your_key         # 默认显示转义字符:"\xe4\xbd\xa0\xe5\xa5\xbd"
127.0.0.1:6379> RAW GET your_key     # 使用 RAW 模式输出
你好

为什么手动复制redis的value到测试环境,会无法解析

根本原因:手动复制破坏了序列化结构
1.序列化器的隐式元信息丢失

当程序使用带类型签名的序列化器(如SpringBoot默认的JdkSerializationRedisSerializerGenericJackson2JsonRedisSerializer)时,数据中会保护额外的类型标识:

// GenericJackson2JsonRedisSerializer 写入的数据实际结构
{"@class": "com.example.User",  // 类型签名(Java特有)"name": "张三","age": 30
}
  • 手动复制行为

通过redis-cli复制的是人类可读的字符串表示,而非原始二进制数据->类型签名@class 等元信息被破坏或丢失

序列化的必要性:

  1. 数据格式统一性 Redis底层存储基于字节流,复杂对象(如Java/Python对象)无法直接存储。序列化将对象转为二进制或字符串(如JSON),确保数据可被Redis处理。

  2. 跨语言兼容性 微服务架构中,不同语言服务(如Java写入、Python读取)需通用格式(如JSON/MessagePack)实现数据交换

  3. 存储效率与安全 序列化可压缩数据体积(如MessagePack比JSON小30%),同时避免明文存储敏感信息,并通过类型校验防止注入攻击

二、常见序列化方式及对比

序列化器适用场景优点缺点示例数据类型
StringRedisSerializer简单字符串、数值性能最优,内存占用低,直接存储字符串仅支持基础类型,不支持对象用户Token、计数器
GenericJackson2JsonRedisSerializer复杂对象(嵌套结构、集合)可读性好(JSON格式),跨语言,支持复杂类型性能较低,内存占用较高,需完整get/set方法用户信息、订单数据
JdkSerializationRedisSerializerJava对象支持任意Java对象(需实现Serializable)二进制不可读,体积大(JSON的5倍),仅限Java特定Java对象
自定义序列化特殊需求(如Protobuf)灵活性高,可优化性能/体积
关键对比:
  • 性能 StringRedisSerializer > GenericJackson2Json > JDK序列化

  • 存储体积:JDK二进制 > JSON > MessagePack/Protobuf

  • 调试友好性:JSON > 字符串 > 二进制

选型建议与最佳实践

1.高性能场景(如缓存热点数据)
  • 优先使用 StringRedisSerializer(Key/Value均适用)

  • 复杂对象手动转为JSON存储,避免全局使用JSON序列化器

// Java示例:手动序列化对象
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(user);
redisTemplate.opsForValue().set("user:1001", json);  // 使用String序列化器
2.跨语言或复杂对象场景
  • 使用 GenericJackson2JsonRedisSerializer,但需确保对象有无参构造器和完整get/set方法

  • 避免Jackson2JsonRedisSerializer(需指定Class类型,灵活性差)

3.规避JDK默认序列化
  • 默认的JdkSerializationRedisSerializer因性能差、体积大、语言绑定强,不推荐生产使用

4.进阶优化
  • 压缩大对象:对超过1KB的数据启用GZIP压缩

  • 版本控制:Key中嵌入版本号(如user:v2:1001),应对字段变更

  • 空值缓存:防止缓存穿透

相关文章:

  • 嵌入式学习笔记C语言阶段--16函数指针
  • YOLOv3 中的 NMS 详解(基于论文与 Darknet 实现)
  • C#设计模式之AbstractFactory_抽象工厂_对象创建新模式-学习
  • 使用 socat 和 xinetd 将程序绑定到端口运行
  • 安卓9.0系统修改定制化____默认开启 开发者选项中的OEM锁解锁选项 开搞篇 五
  • Milvus/ES 插入方案对比
  • OD 算法题 B卷【最多团队】
  • SeaTunnel与Hive集成
  • Mkdocs 阅读时间统计插件
  • 华为云Flexus+DeepSeek征文 | 基于华为云ModelArts Studio搭建PandaWiki知识库问答系统
  • 极客时间《后端存储实战课》阅读笔记
  • linux 阻塞和非阻塞
  • 【一天一个知识点】RAG 是“问答脑”,智能体是“有行动力的大脑”
  • XP POWER EJ ET EY FJ FR 系列软件和驱动程序和手侧
  • 『uniapp』onThemeChange监听主题样式,动态主题不正确生效,样式被覆盖的坑
  • 如何提高电脑打字速度?
  • PHP Swoft2 框架精华系列:Controller 控制器组件解析,用法详解
  • leetcode 1432. 改变一个整数能得到的最大差值 中等
  • PCB设计教程【大师篇】stm32开发板PCB布线(电源部分)
  • 基于C_PSO与BP神经网络回归模型的特征选择方法研究(Python实现)
  • 互联网行业网站模板/刚刚发生 北京严重发生
  • 深圳好的外贸网站建设/网络优化网站
  • wordpress添加vip用户组/外贸seo网站
  • 做网站用的主机多少合适/百度风云榜小说榜排名
  • 寿光市建设局网站/企业网站模板免费
  • b2b的特点有哪些/企业seo优化服务