最近一直在老家遠程辦公,微信突然響了下,有同事說遇到了一個奇怪的問題,讓我幫忙看下。
現象就是標題所說的緩存獲取不到的問題,我一聽感覺這個問題挺有意思的,決定一探究竟。
下面給出部分代碼還原下案發現場:
@CreateCache(name = "demo", expire = 600)
private Cache<String, ThirdPartyEventResponse> cache;
@Test
public void test() {
ThirdPartyEventResponse eventResponse = new ThirdPartyEventResponse();
eventResponse.setTicketCategories(Arrays.asList(ticketCategoryResponse));
// 省略 .....
// 添加
cache.put(DisChannelType.PIAONIU.getValue(), eventResponse);
// 獲取
ThirdPartyEventResponse resp = cache.get(DisChannelType.PIAONIU.getValue());
}
Put之后馬上Get,居然獲取不到值。這就有點匪夷所思了,我們來好好排查下。
首先過期時間為600秒,肯定不是剛保存就過期了的原因。
然后去Redis中查看到底有沒有Put進去,發現數據在Redis中已經存在了,證明插入沒問題。
只有使出終極必殺器了,那就是debug源碼。
通過get方法一直往下看,最終到了RedisCache里面。
然后在這里打個斷點,看看到底有沒有獲取到Redis中的值,驚訝的發現,值是獲取到了的,如下:
納尼,這是什么操作。摸了摸我還沒禿頂的后腦勺,我鎖定了下面這行代碼:
CacheValueHolder<V> holder = (CacheValueHolder)this.valueDecoder.apply(bytes);
猜測應該是解碼的時候出問題了,然后找到了對應的解碼的代碼,用的是kryo框架。
終於在最后一步解碼的時候發現了錯誤,守得雲開見月明啊!
錯誤告訴我們ArrayList缺少構造函數呀,請注意是Arrays里面的ArrayList。嚇得我趕緊看下代碼,果真是Arrays.asList()構造的參數。
*解決辦法自然就很簡單了,直接用 *java.util.ArrayList即可。
最后想說的是解決問題最重要的是方式和技巧。寫這篇文章的目的也是希望大家在遇到問題的時候不要局限於表面,可以往深一點去探索。