在項目中需要用到redis做緩存,于是采用spring-data-redis,并且打算自己封裝一個redis的靜態(tài)工具類。后來在進行單元測試的過程中發(fā)現(xiàn)了一個容易出錯的地方,于是打算記錄下來,并分享給各位朋友。
這里主要說下碰到的問題,首先,采用了spring-data-redis(以下簡稱SDR)中的Template進行redis的操作。
因為考慮到后期的使用場景,于是同時采用了StringRedisTemplate和RedisTemplate,并且對存儲String與存儲Java對象采用不同的Template進行了簡單的封裝。
首先是測試 保存與取出方法。分別用不同的template可以完美通過。
然后在測試刪除的方法中,測試出現(xiàn)了問題。
問題如下:
在采用StringRedisTemplate進行保存的數(shù)據(jù),用StringRedisTemplate去刪除可以成功刪除。
在采用RedisTemplate進行保存的數(shù)據(jù),用RedisTemplate去刪除也可以刪除成功。
在用RedisTemplate去刪除StringRedisTemplate保存的數(shù)據(jù)時,發(fā)現(xiàn)刪除失敗。
在用StringRedisTemplate去刪除RedisTemplate保存的數(shù)據(jù)時,刪除失敗。
因為,需要封裝一套通用的刪除方法,并且需要封裝一個批量刪除的方法。所以研究了下問題出現(xiàn)的原因。
經(jīng)過查看SDR官方給出的文檔,發(fā)現(xiàn)是因為序列化策略的問題。
這里簡單說下:
SDR默認采用的序列化策略有兩種,一種是String的序列化策略,一種是JDK的序列化策略。
StringRedisTemplate默認采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。StringRedisSerializer
RedisTemplate默認采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。JdkSerializationRedisSerializer
就是因為序列化策略的不同,即使是同一個key用不同的Template去序列化,結(jié)果是不同的。所以根據(jù)key去刪除數(shù)據(jù)的時候就出現(xiàn)了刪除失敗的問題。
解決方法如下,手動指定RedisTemplate的key的序列化策略
[xml]view plaincopyprint?
<!--?redis?序列化策略?,通常情況下key值采用String序列化策略,?-->??
<!--?如果不指定序列化策略,StringRedisTemplate的key和value都將采用String序列化策略;?-->??
<!--?但是RedisTemplate的key和value都將采用JDK序列化?這樣就會出現(xiàn)采用不同template保存的數(shù)據(jù)不能用同一個template刪除的問題?-->??
<bean?id="stringRedisSerializer"???
class="org.springframework.data.redis.serializer.StringRedisSerializer"?/>??
<bean?id='redisWriteTemplate'?class="org.springframework.data.redis.core.RedisTemplate">??
<property?name="connectionFactory"?ref="jedisWriteConnectionFactory"?/>??
<property?name="keySerializer"?ref="stringRedisSerializer"?/>??
<property?name="hashKeySerializer"?ref="stringRedisSerializer"?/>??
</bean>??
<!--?redis?序列化策略?,通常情況下key值采用String序列化策略,?-->
<!--?如果不指定序列化策略,StringRedisTemplate的key和value都將采用String序列化策略;?-->
<!--?但是RedisTemplate的key和value都將采用JDK序列化?這樣就會出現(xiàn)采用不同template保存的數(shù)據(jù)不能用同一個template刪除的問題?-->
<bean?id="stringRedisSerializer"?
????class="org.springframework.data.redis.serializer.StringRedisSerializer"?/>
<bean?id='redisWriteTemplate'?class="org.springframework.data.redis.core.RedisTemplate">
????<property?name="connectionFactory"?ref="jedisWriteConnectionFactory"?/>
????<property?name="keySerializer"?ref="stringRedisSerializer"?/>
????<property?name="hashKeySerializer"?ref="stringRedisSerializer"?/>
</bean>
這樣就能完美的刪除了。
這里推薦將所有Template的key都采用String的序列化方式,而value的序列化方式可以采用不同的序列化方式。(jreids自動選擇)(這樣還有一個好處就是不必string的也采用jdk的序列化從而導常用數(shù)據(jù)格式致為了存儲數(shù)據(jù)結(jié)構(gòu)浪費空間)
另外 出來這兩個序列化方式之外,SDR還提供了 ?
JacksonJsonRedisSerializer
Jackson2JsonRedisSerializer
OxmSerializer
等序列化方法,大家可以分別采用各種序列化方式做一些試驗。
如果你想學好JAVA這門技術,也想在IT行業(yè)拿高薪,可以參加我們的訓練營課程,選擇最適合自己的課程學習,技術大牛親授,8個月后,進入名企拿高薪。我們的課程內(nèi)容有:Java工程化、高性能及分布式、高性能、深入淺出。高架構(gòu)。性能調(diào)優(yōu)、Spring,MyBatis,Netty源碼分析和大數(shù)據(jù)等多個知識點。如果你想拿高薪的,想學習的,想就業(yè)前景好的,想跟別人競爭能取得優(yōu)勢的,想進阿里面試但擔心面試不過的,你都可以來,q群號為:180705916 進群免費領取學習資料。