❶ 因在缓存对象中增加字段,导致Redis出现反序列化失败的问题
因为业务需求的需要,我们需要在原来项目中的一个DTO类中新增两个字段(我们项目使用的是bbo架构,这个DTO在A项目/服务的domain包中,会被其他的项目如B、C、D引用到)。但是这个DTO对象已经在Redis缓存中存在了, 如果我们直接向类中增加字段而不做任何处理的话,那么查询操作查出来的缓存对象就会报反序列化失败的错误,从而影响正常的业务流程 ,那么来看一下我的解决方案吧。
我们的正式环境和预发布环境是共用Redis和Mysql。如果修改了DTO且没有加@JsonIgnoreProperties(ignoreUnknown = true)这个注解。
那么DTO所在的A项目发到预发布之后,会启动一个后台定时任务把最新的DTO对象刷新到缓存中去,但是除了这个工程以外的其他依赖服务如果没有发的话,那么他们jar包里面的domain还是旧的DTO。那么这个时候取出来的缓存(最新的DTO的缓存)就会有反序列化的错误,发包的延迟和预发布验证的时间都会导致线上反序列化失败,从而阻塞业务。
解决方案就是升级缓存的版本号(修改原来缓存DTO的Redis的Key值)
缓存key升级版本号,在其他未更新的应用中的缓存key已经在跑的jar包里面,他们的key是旧的,比如v1,那么v1对应的DTO就是旧的DTO。升级后新的DTO版本为v2那么发起来的自身服务刷新最新的DTO缓存是放到v2的key里面的,即v2->新的DTO,v1->旧的DTO。这样可以保证不会有反序列化的问题。
改版本号一定要在第一次发的时候改上去才好,不然你按v1发的版,发现问题再改成v2已经就晚了,因为已经把新的DTO刷到v1里面了,线上的依赖服务里面的domain包就是v1捞出来肯定异常。如果发生这种情况只能再发v2版本到预发布,同时删掉线上v1的缓存。
我是 “翎野君” ,感谢各位朋友的: 点赞 、 收藏 和 评论 ,我们下期见。
❷ shiro的session信息放redis反序列化异常解决
背景
在本地session移至redis存储时,原本以为引入spring-session-data-redis依赖,配置RedisHttpSessionConfiguration,在web.xml中引入springSessionRepositoryFilter就结束了,没想到遇到序列化相关的问题,具体就是只有getter,没有setter。日志如下:
分析
提示很清楚,就是shiro的SimplePrincipalCollection类中realmNames字段没有setter方法,没法反序列化。
来看看realmNames是什么鬼,作为成熟的框架也偷懒不写setter?仔细一看,发现并不简单。类里面没有realmNames,只有个getRealmNames方法。
原来是个假getter,是由其他字段动态生成的,如下:
看下redis里面存的值
核心就是objectMapper.addMixIn()和objectMapper.setFilters()两个方法
SimplePrincipalCollection是需要处理的类,IncludShiroFields就是一个简单的接口,如下:
通过上面的配置间接控制SimplePrincipalCollection类中必要字段的序列化,从而解决了问题。
ps :因为使用了注解,一定要去掉objectMapper.configure(MapperFeature.USE_ANNOTATIONS, false),不然配置不生效。
❸ redis在加入缓存的对象取出来的时候反序列化一定要是原来的对象吗
java把对象从内存放到硬盘为啥需要序列化?内存可能是用堆栈、寄存器存储的,断电后消失(RAM);但是磁盘不一样,磁盘固化数据(ROM)。
需
要序列化,主要是一种针对需要I/O操作的,此时写入磁盘恰巧需要I/O。让类实现serializable接口,此类的对象就可以被序列化了。针对对象
的对象流:ObjectOutputStream,调用writeObject()/readObject()可以实现序列化、反序列化。
❹ 2022-03-12 SpringBoot 使用redis做缓存,设置失效时间以及序列化
SpringBoot的cache缓存,是针对返回值的一种操作
springboot使用redis做缓存时,默认只需要导入redis依赖,即可实现使用redis做缓存
不需要导入cache依赖
在启动类上加上 @EnableCaching 即可开启缓存功能
关于各个注解的使用,这里不再细说,网上详细的教程很多,这里主要讲一下如何指定过期时间
默认是永不过期,如果需要指定过期时间,则需要增加配置类