❶ 因在緩存對象中增加欄位,導致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 即可開啟緩存功能
關於各個註解的使用,這里不再細說,網上詳細的教程很多,這里主要講一下如何指定過期時間
默認是永不過期,如果需要指定過期時間,則需要增加配置類