UserCache.getUser方法出现的反序列化问题

Blade 已结 1 23
yizd
yizd 剑童 4小时前

一、该问题的重现步骤是什么?

1. 在User类中新增字段并使用maven deploy为最新版本,在redis中缓存了包含此新字段的User数据

2. 在使用旧版本的user-api的服务中,使用了UserCache.getUser方法的地方会报org.springframework.data.redis.serializer.SerializationException: Could not read JSON:Unrecognized field "xxx" (class org.springblade.system.pojo.entity.User)错误

3.目前通过升级最新user-api版本解决了此问题


二、你期待的结果是什么?实际看到的又是什么?

期待:User类新增字段不影响UserCache.getUser方法

实际:使用了UserCache.getUser方法的地方会报org.springframework.data.redis.serializer.SerializationException: Could not read JSON:Unrecognized field "xxx" (class org.springblade.system.pojo.entity.User)错误


三、你正在使用的是什么产品,什么版本?在什么操作系统上?

bladex 4.3.0.RELEASE

win10

四、请提供详细的错误堆栈信息,这很重要。

org.springframework.data.redis.serializer.SerializationException: Could not read JSON:Unrecognized field "accountFlag" (class org.springblade.system.pojo.entity.User), not marked as ignorable (36 known properties: "deptId", "nation", "realName", "name", "isDeleted", "avatar", "homeDistrictCode", "id", "email", "createDept", "passwordHmac", "tenantId", "sex", "createUser", "companyName", "createTime", "code", "phone", "roleId", "status", "updateUser", "phoneHmac", "updateTime", "homeCityCode", "idNo", "birthday", "password", "userType", "userCategory", "account", "passwordUpdateTime", "idType", "homeProvinceCode", "postId", "applicationReason", "position"])

 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1007] (through reference chain: org.springblade.system.pojo.entity.User["accountFlag"]) 

at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:292) ~[spring-data-redis-3.2.12.jar:3.2.12]

at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:261) ~[spring-data-redis-3.2.12.jar:3.2.12]

at org.springframework.data.redis.serializer.DefaultRedisElementReader.read(DefaultRedisElementReader.java:46) ~[spring-data-redis-3.2.12.jar:3.2.12]

at org.springframework.data.redis.serializer.RedisSerializationContext$SerializationPair.read(RedisSerializationContext.java:277) ~[spring-data-redis-3.2.12.jar:3.2.12]

at org.springframework.data.redis.cache.RedisCache.deserializeCacheValue(RedisCache.java:390) ~[spring-data-redis-3.2.12.jar:3.2.12]

at org.springframework.data.redis.cache.RedisCache.lookup(RedisCache.java:209) ~[spring-data-redis-3.2.12.jar:3.2.12]

at org.springframework.cache.support.AbstractValueAdaptingCache.get(AbstractValueAdaptingCache.java:58) ~[spring-context-6.1.15.jar:6.1.15]

at org.springblade.core.cache.utils.CacheUtil.get(CacheUtil.java:219) ~[blade-starter-cache-4.3.4.RELEASE.jar:4.3.4.RELEASE]

at org.springblade.core.cache.utils.CacheUtil.get(CacheUtil.java:197) ~[blade-starter-cache-4.3.4.RELEASE.jar:4.3.4.RELEASE]

at org.springblade.system.cache.UserCache.getUser(UserCache.java:76) ~[blade-user-api-1.0.8.RELEASE.jar:na]

五、若有更多详细信息,请在下面提供。

1条回答
  •  admin
    admin (最佳回答者)
    1小时前

    更新了字段后,旧版本的缓存需要清理后才可以正常序列化的,这种情况下你清下redis缓存就可以

    作者追问:1小时前

    感谢回复!

    我看UserCache.getUser方法,如果缓存中没有,会从数据库中查询数据放到缓存中。

    举个例子,现在缓存清掉,A服务依赖的是最新的user-api,他放到缓存中的user数据就会有新字段,此时B服务依赖的是旧版本的user-api,它从缓存中获取的是有新字段的缓存,这个时候他就会出现反序列化报错的。

    清缓存后,就看哪个服务优先把user数据存缓存了,如果是B服务优先,那缓存中的user数据就没有新字段。如果是A服务优先,缓存中的user数据就会有新字段的,这时依赖user-api旧版本的服务就会有反序列化问题。

    请问这种是不是只能让依赖旧版本的升级最新的user-api呢?如果要能兼容旧版本,redis的配置可以怎么改造吗?


    回答: 1小时前

    原理很简单,只要缓存的类的字段和你现有的类的字段不匹配就会实例化失败。

    所以有字段变动,就更新需要依赖的最新版本。

    0 讨论(1)
提交回复