踩坑,Redis
缓存使用Jackson2JsonRedisSerializer
管理序列化,未设置disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
,上线中新代码写入了新的缓存字段结构,旧代码读到新结构报错UnrecognizedPropertyException
。
背景
a
服务上线,在b
表新增字段c
。
bDTO
为缓存对象且对其他服务暴露。对象结构如下:
|
|
上线两台实例,发现有报错:
Could not read JSON: Unrecognized field "c"
nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "c"
第一步动作:先回滚。
分析
第二步动作:查具体原因。
可以看到报了一个jackson
解析的异常。
对应的查询接口为:
/url/d
迅速拉当时的rd
了解一下接口背景:
- 前两个月增加了此读缓存接口;
- 接口会在登录某系统处调用,影响范围较大;
调用缓存大概是这样的:
|
|
接口通过@Cacheable
加了一层缓存,逻辑为查b
表信息。
关联变更:本次上线 b 上新增了 c 字段。
根据报错,看下jackson的设计: https://stackoverflow.com/questions/4486787/jackson-with-json-unrecognized-field-not-marked-as-ignorable
所以问题是这样产生的:
- 新的代码发布,缓存写入了带新字段的
json
; - 旧的代码读缓存,报错
- 原因1:旧代码的
b
结构是旧的; - 原因2:
cacheable
使用的redis
序列化方式为Jackson2JsonRedisSerializer
,对应objectMapper
未设置disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
;
- 原因1:旧代码的
解决
第三步动作:解决问题。
cacheable redis
序列化设置,增加disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
,反序列化时会忽略class
中没有的属性;- 作用是:防止以后报此类错;
queryBusinessInfo
缓存key
更名,防止发布中老代码读到新写入的数据;- 作用是:防止发布中报此错;