redis 反序列化deserialize异常问题解决

本文详细解析了在使用Spring Boot整合Redis时,出现的序列化与反序列化异常问题。主要原因是不同系统间共享Redis资源,导致对象序列化路径不匹配引发的ClassNotFound异常。文章提供了具体的解决方案,即清理Redis缓存,确保对象序列化路径的一致性。

异常信息

 

ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is org.springframework.core.NestedIOException: Failed to deserialize object type; nested exception is java.lang.ClassNotFoundException: com.xxx.tpam.dao.model.Dict] with root cause

java.lang.ClassNotFoundException: com.xxx.tpam.dao.model.Dict

分析:这个错误提示找不到类,反序列化的时候报错,而对象系列化时是跟对象所处的包路径相关的。

 

我本地测试,几个系统用的同一个redis,对象在一个系统中序列化存入redis,包路径com.xxx.tpam.dao.model.Dict;主要原因是因为key也是相同,在运行另一个系统时,发现这个key已经存在了,取出时,因当前这个系统包路径为com.xxx.book.dao.model.Dict,由于两个对象的类所处的包路径不一致,反序列化失败,因而报找不到类错误。

解决方法:

直接删除redis中对应的值即可

我是使用的本地库,就直接在redis-cli 执行了flushall(删除所有数据库中的所有key ) 命令

 

 

### Redis 反序列化失败的原因 Redis 反序列化失败通常发生在尝试从 Redis 中读取数据并将其转换为 Java 对象的过程中。以下是可能导致此问题的主要原因及其对应的解决方案: #### 1. **序列化 ID 不匹配** 当实体类实现 `Serializable` 接口时,如果没有显式定义 `serialVersionUID` 或者不同版本的类具有不同的 `serialVersionUID`,则可能会导致反序列化失败[^3]。 - **解决方案**: 确保所有涉及序列化的类都明确定义了唯一的 `serialVersionUID`,并且在多个系统之间保持一致性。 ```java private static final long serialVersionUID = 1L; ``` --- #### 2. **类结构发生变化** 如果存储到 Redis 的对象与其当前加载的类结构不一致(例如新增或删除字段),也会引发反序列化错误。 - **解决方案**: 清理旧的缓存数据或将新字段标记为可选(如使用 Jackson 注解)。对于已存在的数据,可以考虑兼容处理逻辑。 ```java @JsonInclude(JsonInclude.Include.NON_NULL) public class Example { private String field1; @JsonProperty("newField") // 新增字段兼容处理 private String optionalField; } ``` --- #### 3. **使用的序列化器不匹配** 默认情况下,Spring 使用 JdkSerializationRedisSerializer 进行序列化/反序列化操作。然而,这种序列化方式会产生不可读的字节数组,并且容易与其他工具冲突。如果切换至其他序列化器(如 Jackson),未正确配置也可能导致反序列化失败[^2]。 - **解决方案**: 统一使用相同的序列化器。推荐采用更高效的 JSON 序列化器(如 Jackson)替代 JDK 默认序列化器。 ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); // 设置键和值的序列化器 GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(); template.setDefaultSerializer(serializer); return template; } } ``` --- #### 4. **Redis 数据被篡改或损坏** 如果 Redis 存储的数据被意外修改或者由于网络传输等原因发生损坏,则会导致反序列化失败[^1]。 - **解决方案**: 验证 Redis 数据的一致性和完整性。可以通过定期备份 Redis 数据以及设置合理的过期时间来减少此类风险。 --- #### 5. **依赖库版本差异** 不同 Spring Boot 版本之间的序列化机制可能存在细微差别,尤其是在升级过程中引入的新特性或修复补丁会影响现有行为。 - **解决方案**: 确保所有参与系统的 Spring Boot 和相关依赖版本完全一致。必要时查阅官方文档确认是否存在已知问题。 --- ### 总结 Redis 反序列化失败的根本原因是序列化与反序列化过程中的不一致性。通过明确 `serialVersionUID`、维护稳定的类结构、选用合适的序列化器以及保障环境一致性等方式能够有效解决问题。 ```python # 示例代码展示如何自定义 Redis 配置以避免反序列化异常 from redis import Redis import json def serialize(obj): """ 将 Python 对象序列化为 JSON 字符串 """ return json.dumps(obj) def deserialize(data): """ 将 JSON 字符串反序列化为 Python 对象 """ try: return json.loads(data) except Exception as e: raise ValueError(f"Deserialization failed: {e}") # 初始化 Redis 客户端 client = Redis(host='localhost', port=6379, db=0) key = 'example_key' value = {'name': 'Alice', 'age': 25} # 存储前先序列化 serialized_value = serialize(value) client.set(key, serialized_value) # 获取后立即反序列化 stored_data = client.get(key).decode('utf-8') deserialized_value = deserialize(stored_data) print(deserialized_value) ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值