当前位置: 首页 > 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),应对字段变更

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

http://www.xdnf.cn/news/1049941.html

相关文章:

  • 以笔为剑,破茧成蝶
  • 华为云Flexus+DeepSeek征文 | 基于华为云ModelArts Studio平台与Cherry Studio搭建知识库问答助手
  • 手机SIM卡通话中随时插入录音语音片段(Android方案)
  • C++20 核心特性详解:现代C++的进化里程碑
  • PyTorch 实现 MNIST 手写数字识别
  • Python训练营---DAY54
  • 子集筛选(Select by Data Index)组件研究
  • 2025年ASOC SCI2区TOP,多策略组合鲸鱼优化算法SCWOA+梯级水库调度,深度解析+性能实测
  • 线上GC count突增问题排查及修复记录
  • 创新项目实训纪实——总结与反思
  • 62-STM32的ISP一键下载电路
  • 如何判断一个项目是否有问题
  • MIT线性代数第一讲笔记
  • LlamaRL 大规模分布式异步强化学习框架
  • Java中hashCode方法与equal方法何时重写
  • 一夜冲刺!!微机原理与接口
  • 无人机指南
  • 常见内核TCP参数描述与配置
  • Django中间件讲解
  • sparseDrive(1): 论文解读
  • 【C++】简单商品价格计算程序练习
  • Day01_刷题niuke20250615
  • Axure应用交互设计:中继器数据向多种类型元件赋值
  • 产品经理页面布局设计的四维思考框架
  • 湖北理元理律师事务所:债务优化中如何保障债务人生存权益
  • Vim命令总结
  • Python类中的特殊方法详解
  • 第十七章:SD如何制作三视图(基础)
  • 计算机操作系统(计算题公式)
  • 在VMware虚拟机集群中,完成Hive的安装部署