SerializationException: Cannot deserialize 的根本原因是存取时序列化/反序列化规则不匹配,最常见于:1)存用JdkSerializationRedisSerializer而取用StringRedisSerializer或Jackson;2)多系统共用Redis但序列化策略不统一;3)配置RedisTemplate时仅设valueSerializer却遗漏hashKeySerializer和hashValueSerializer,导致Hash操作失败。

报错 SerializationException: Cannot deserialize 怎么快速定位原因
这不是 Redis 连不上,而是数据存进去和取出来时序列化/反序列化规则对不上。最常见三种情况:
— 存数据用的是 JdkSerializationRedisSerializer(默认),取数据时却用了 StringRedisSerializer 或 Jackson2JsonRedisSerializer;
— 多个系统共用一个 Redis 实例,A 系统用 JSON 存,B 系统用 JDK 序列化读,直接炸;
— 自定义了 RedisTemplate 但只设了 valueSerializer,没同步设 hashKeySerializer、hashValueSerializer,操作 Hash 时就崩。
redisTemplate 的 key 和 value 序列化必须成对配置
只改 setValueSerializer 不够,key、hash key、hash value 都得统一。否则 opsForHash().put() 这类操作会静默失败或报 SerializationException。
正确做法是:
- key 和 hash key 一律用
StringRedisSerializer(人类可读、跨语言兼容) - value 和 hash value 按需选:简单字符串用
StringRedisSerializer;对象用Jackson2JsonRedisSerializer(注意类要带无参构造、字段 public 或有 getter/setter) - 别漏掉
setHashKeySerializer和setHashValueSerializer—— 这是最多被跳过的两行
示例片段:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(User.class)); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(User.class));
用 Jackson2JsonRedisSerializer 时,Unrecognized field 或 Cannot construct instance of 怎么办
这是 Jackson 反序列化失败的典型提示,不是 Redis 问题,是类结构和 JSON 不匹配。
常见原因和对策:
- 实体类缺少无参构造方法 → 补上
public User() {} - 字段是 private 且没 getter/setter → 加上对应方法,或用
@JsonProperty标注字段 - JSON 里有字段,Java 类里没有 → 加
@JsonIgnoreProperties(ignoreUnknown = true)到类上 - 用了
enableDefaultTyping导致写入带类型信息(如["com.example.User", {...}]),但读的时候没配对应反序列化器 → 去掉activateDefaultTyping,或确保读写两端配置完全一致
老系统数据混用时,怎么安全读取不爆异常
如果 Redis 里已有其他系统写入的数据(比如用 JDK 序列化存的 byte[]),而你新项目用 JSON,直接 redisTemplate.opsForValue().get(key) 必然报错。
此时不要全局换序列化器,而是按需切换:
- 对新 key,走标准 JSON 流程
- 对老 key,单独封装一个安全读取方法,用
redisTemplate.execute()手动指定StringRedisSerializer解析 - 避免在同一个
RedisTemplatebean 上反复切换序列化器 —— 容易线程不安全、状态污染
关键点:序列化策略不是“设一次就万事大吉”,它绑定在每个 RedisTemplate 实例上,混用场景下,要么清空旧数据,要么隔离读写路径。

















