springboot中使用redis详解
一、redis簡介
redis是一款高性能key-value(鍵值對)內存型數據庫,是非關系型數據庫的一種,它采用單線程的架構方式,避免了多線程存在的鎖處理造成的資源耗費,讀取速度非常快,非常適合變化不是太大但數據量很大的數據的存儲和讀取。
redis中的數據類型:String、list、hash、zset、set五種。
二、使用場景
項目中涉及到數據查詢的操作,先從redis中查詢,若redis中不存在則從數據庫中查詢,再更新到redis中,以后再次執行相同的查詢則直接從redis中查詢,提高了效率。
三、springboot中使用redis
2、application.properties中配置redis相關的參數
##配置redis spring.redis.database=0 spring.redis.host=119.3.250.240 spring.redis.password=888888 spring.redis.port=63793、使用redis
redis中有兩個模板類:RedisTemplate和StringRedisTemplate。通過模板類可以對redis數據庫進行增刪改查的操作,redis數據庫中存放數據是要對key、value進行序列化的,RedisTemplate模板類默認采用JdkSerializationRedisSerializer序列化類對key和value進行序列化;而StringRedisTemplate默認采用StringRedisSerializer序列化類對key和value進行序列化。
上面說了這么多理論有啥用?對項目有什么影響?如何在項目中使用呢?別急,咱們下面就結合代碼進行說明。
1)如果采用StringRedisTemplate模板,首先看它的下源碼:
/** 從源碼中可以看到,StringRedisTemplate模板類默認采用StringRedisSerializer序列化類對 key和value進行序列化,通過該模板類傳參時,key和value要求是String類型。 */ public class StringRedisTemplate extends RedisTemplate<String, String> {public StringRedisTemplate() {this.setKeySerializer(RedisSerializer.string());this.setValueSerializer(RedisSerializer.string());this.setHashKeySerializer(RedisSerializer.string());this.setHashValueSerializer(RedisSerializer.string());}public StringRedisTemplate(RedisConnectionFactory connectionFactory) {this();this.setConnectionFactory(connectionFactory);this.afterPropertiesSet();}protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {return new DefaultStringRedisConnection(connection);} }下面用StringRedisTemplate做個小測試:
@SpringBootTest class DemoApplicationTests {//使用StringRedisTemplate模板@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void junitTest() {//往redis中存入key、value鍵值對stringRedisTemplate.opsForValue().set("webAddress","www.54gwz.cn");//從redis中取出key對應的value值System.out.println("---webAddress-->"+stringRedisTemplate.opsForValue().get("webAddress"));} }//單元測試日志截取如下: 2020-06-17 11:21:39.891 INFO 77817 --- [ main] io.lettuce.core.EpollProvider : Starting without optional epoll library 2020-06-17 11:21:39.894 INFO 77817 --- [ main] io.lettuce.core.KqueueProvider : Starting without optional kqueue library ----------------webAddress----------->www.54gwz.cnredis客戶端查詢結果如下:
119.3.250.240:6379> keys * 1) "webAddress" 119.3.250.240:6379> get webAddress "www.54gwz.cn"2)如果采用RedisTemplate模板,首先看下它的源碼(部分截取):
通過源碼分析得到key、value、hashKey、hashValue均默認采用JdkSerializationRedisSerializer方式進行了序列化。
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {private boolean initialized = false;private boolean enableDefaultSerializer = true;@Nullableprivate RedisSerializer<?> defaultSerializer;@Nullableprivate RedisSerializer keySerializer = null;@Nullableprivate RedisSerializer valueSerializer = null;@Nullableprivate RedisSerializer hashKeySerializer = null;@Nullableprivate RedisSerializer hashValueSerializer = null;private RedisSerializer<String> stringSerializer = RedisSerializer.string();public RedisTemplate() {}public void afterPropertiesSet() {super.afterPropertiesSet();boolean defaultUsed = false;//defaultSerializer默認序列化類為JdkSerializationRedisSerializerif (this.defaultSerializer == null) {this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());}/**key、value、hashKey、hashValue均默認采用JdkSerializationRedisSerializer的方式進行了序列化*/if (this.enableDefaultSerializer) {if (this.keySerializer == null) {this.keySerializer = this.defaultSerializer;defaultUsed = true;}if (this.valueSerializer == null) {this.valueSerializer = this.defaultSerializer;defaultUsed = true;}if (this.hashKeySerializer == null) {this.hashKeySerializer = this.defaultSerializer;defaultUsed = true;}if (this.hashValueSerializer == null) {this.hashValueSerializer = this.defaultSerializer;defaultUsed = true;}}if (this.enableDefaultSerializer && defaultUsed) {Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");}if (this.scriptExecutor == null) {this.scriptExecutor = new DefaultScriptExecutor(this);}this.initialized = true;}下面我們用這種默認的JdkSerializationRedisSerializer序列化的方式進行一個小測驗:
@SpringBootTest class DemoApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void junitTest() {redisTemplate.opsForValue().set("username","wangxinli");System.out.println("---username-->"+redisTemplate.opsForValue().get("username"));} } 執行單元測試打印日志結果:(結果正確!) 2020-06-17 17:57:40.440 INFO 1373 --- [main] io.lettuce.core.EpollProvider: Starting without optional epoll library ----------------username----------->wangxinli此時在redis客戶端進行查詢:發現username前面會有一連串特殊字符,原因在于key值進行了JdkSerializationRedisSerializer序列化,如果想去掉key值的特殊字符,需要對key值指定序列化方式。
119.3.250.240:6379> keys * 1) "\xac\xed\x00\x05t\x00\busername" 2) "webAddress"自定義序列化方式:
@Configuration public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();//指定key、hashKey的序列化方式為StringRedisSerializerredisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());//指定value、hashValue的序列化方式為JdkSerializationRedisSerializerredisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());//redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class));redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.afterPropertiesSet();return redisTemplate;} }再次執行看下效果:
@SpringBootTest class DemoApplicationTests {/**此處自動裝配的RedisTemplate對象的序列化方式就是上面自定義的,即(key和hashKey采用StringRedisSerializer,value和hashValue采用的 JdkSerializationRedisSerializer)*/@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void junitTest() {redisTemplate.opsForValue().set("usernameSerialize","wangxinliSerialize");System.out.println("---usernameSerialize-->"+redisTemplate.opsForValue().get("usernameSerialize"));} }執行單元測試,看下打印的日志效果:(沒有問題)
2020-06-17 18:27:24.330 INFO 1738 --- [main] io.lettuce.core.EpollProvider 2020-06-17 18:27:24.331 INFO 1738 --- [main].....省略 ---usernameSerialize-->wangxinliSerialize再看下redis客戶端:發現usernameSerialize前面的特殊字符消失了,我們的更改序列化方式
生效啦,我們成功啦!!!!
但別高興的太早,有沒有發現一個新的問題呢,usernameSerialize對應的value值也變成有特殊字符啦!!!!別擔心,這是正常現象,因為value值也是采用的JdkSerializationRedisSerializer進行序列化的鴨!我們也可以采用上述指定序列化的方式進行更改。
注意一點:若采用JdkSerializationRedisSerializer序列化value、hashValue,則需要model中的類實現Serializable接口,此外還有Jackson2JsonRedisSerializer序列化方式,使用它不需要model實現Serializable接口。
總結
以上是生活随笔為你收集整理的springboot中使用redis详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Springboot中使用jpa
- 下一篇: RedisTemplate中opsFor