Skip to content

序列化器体系

This content is not available in your language yet.

Redis 只接收字节数组,Spring Data Redis 用 serializer 把类型边界显式化,并为 key、value、hash key、hash value 分配独立策略。

先给答案:序列化格式决定 Redis 数据的长期兼容性,而不只是网络传输效率

Section titled “先给答案:序列化格式决定 Redis 数据的长期兼容性,而不只是网络传输效率”

Redis 本身只保存字节,Spring Data Redis 必须为 key、value、hash field 和 hash value 选择序列化器。JSON 可读但需要类型信息,JDK 序列化带有 Java 绑定和安全边界,字符串序列化简单却不适合复杂对象。

更换序列化器会改变已有 key 的可读性和 hash field 行为;同一业务如果读写使用不同配置,会出现“Redis 里有值但反序列化失败”。设计格式时要把升级、跨语言、大小、可信输入和回滚一起考虑。

RedisTemplate
keySerializer -> key bytes
valueSerializer -> value bytes
hashKeySerializer -> hash field bytes
hashValueSerializer -> hash value bytes
stringSerializer -> script/channel/string bytes

RedisSerializer 定义在 serializer/RedisSerializer.java:31-134,只要求 serialize 和 deserialize,并提供 Java、JSON、String、byte[] 工厂方法 :40-86。

DefaultRedisSerializationContext 在 serializer/DefaultRedisSerializationContext.java:30-45 保存五个 SerializationPair,builder 的必填检查在 :142-151。

GenericJackson2JsonRedisSerializer 在 serializer/GenericJackson2JsonRedisSerializer.java:60-80 说明它使用动态类型。serialize 在 :269-281 处理 null 和 JSON 写入,deserialize 在 :301-316 根据类型提示解析对象。

动态类型能让 RedisTemplate<String,Object> 恢复多态对象,但会把类型信息写入数据格式,且扩大反序列化攻击面,生产上应限制可信数据和类型白名单。

替代方案:所有值都用 JDK serialization。 为什么不行:格式不透明、跨语言困难、类演进和安全审计成本高。 证据:项目同时提供 String、JSON、Java 和 byte[] serializer,见 RedisSerializer.java:40-86;模板文档还明确默认 Java serializer,见 RedisTemplate.java:68-84。

场景 现象 原因 规避
key 使用 JSON Redis CLI 中 key 不可读 key 也被对象编码 key 通常使用 String serializer
更换 serializer 老数据无法读取 Redis 中只保存 bytes 版本化 key 或双读迁移
开启动态类型 反序列化风险 类型提示来自外部数据 使用受控类型和可信数据

序列化策略应成为显式 schema,而不是隐含在泛型里;缓存、消息和持久化系统都应考虑格式演进、跨语言与安全边界。

面试锚点

  • 为什么 key 和 value 要分开 serializer?
  • JSON 动态类型解决了什么问题,又引入什么风险?
  • SerializationPair 比直接持有 serializer 多解决了什么?