springboot中使用redis详解
一、redis簡(jiǎn)介
redis是一款高性能key-value(鍵值對(duì))內(nèi)存型數(shù)據(jù)庫(kù),是非關(guān)系型數(shù)據(jù)庫(kù)的一種,它采用單線程的架構(gòu)方式,避免了多線程存在的鎖處理造成的資源耗費(fèi),讀取速度非???#xff0c;非常適合變化不是太大但數(shù)據(jù)量很大的數(shù)據(jù)的存儲(chǔ)和讀取。
redis中的數(shù)據(jù)類(lèi)型:String、list、hash、zset、set五種。
二、使用場(chǎng)景
項(xiàng)目中涉及到數(shù)據(jù)查詢(xún)的操作,先從redis中查詢(xún),若redis中不存在則從數(shù)據(jù)庫(kù)中查詢(xún),再更新到redis中,以后再次執(zhí)行相同的查詢(xún)則直接從redis中查詢(xún),提高了效率。
三、springboot中使用redis
2、application.properties中配置redis相關(guān)的參數(shù)
##配置redis spring.redis.database=0 spring.redis.host=119.3.250.240 spring.redis.password=888888 spring.redis.port=63793、使用redis
redis中有兩個(gè)模板類(lèi):RedisTemplate和StringRedisTemplate。通過(guò)模板類(lèi)可以對(duì)redis數(shù)據(jù)庫(kù)進(jìn)行增刪改查的操作,redis數(shù)據(jù)庫(kù)中存放數(shù)據(jù)是要對(duì)key、value進(jìn)行序列化的,RedisTemplate模板類(lèi)默認(rèn)采用JdkSerializationRedisSerializer序列化類(lèi)對(duì)key和value進(jìn)行序列化;而StringRedisTemplate默認(rèn)采用StringRedisSerializer序列化類(lèi)對(duì)key和value進(jìn)行序列化。
上面說(shuō)了這么多理論有啥用?對(duì)項(xiàng)目有什么影響?如何在項(xiàng)目中使用呢?別急,咱們下面就結(jié)合代碼進(jìn)行說(shuō)明。
1)如果采用StringRedisTemplate模板,首先看它的下源碼:
/** 從源碼中可以看到,StringRedisTemplate模板類(lèi)默認(rèn)采用StringRedisSerializer序列化類(lèi)對(duì) key和value進(jìn)行序列化,通過(guò)該模板類(lèi)傳參時(shí),key和value要求是String類(lèi)型。 */ 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做個(gè)小測(cè)試:
@SpringBootTest class DemoApplicationTests {//使用StringRedisTemplate模板@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void junitTest() {//往redis中存入key、value鍵值對(duì)stringRedisTemplate.opsForValue().set("webAddress","www.54gwz.cn");//從redis中取出key對(duì)應(yīng)的value值System.out.println("---webAddress-->"+stringRedisTemplate.opsForValue().get("webAddress"));} }//單元測(cè)試日志截取如下: 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客戶(hù)端查詢(xún)結(jié)果如下:
119.3.250.240:6379> keys * 1) "webAddress" 119.3.250.240:6379> get webAddress "www.54gwz.cn"2)如果采用RedisTemplate模板,首先看下它的源碼(部分截取):
通過(guò)源碼分析得到key、value、hashKey、hashValue均默認(rèn)采用JdkSerializationRedisSerializer方式進(jìn)行了序列化。
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默認(rèn)序列化類(lèi)為JdkSerializationRedisSerializerif (this.defaultSerializer == null) {this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());}/**key、value、hashKey、hashValue均默認(rèn)采用JdkSerializationRedisSerializer的方式進(jìn)行了序列化*/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;}下面我們用這種默認(rèn)的JdkSerializationRedisSerializer序列化的方式進(jìn)行一個(gè)小測(cè)驗(yàn):
@SpringBootTest class DemoApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void junitTest() {redisTemplate.opsForValue().set("username","wangxinli");System.out.println("---username-->"+redisTemplate.opsForValue().get("username"));} } 執(zhí)行單元測(cè)試打印日志結(jié)果:(結(jié)果正確!) 2020-06-17 17:57:40.440 INFO 1373 --- [main] io.lettuce.core.EpollProvider: Starting without optional epoll library ----------------username----------->wangxinli此時(shí)在redis客戶(hù)端進(jìn)行查詢(xún):發(fā)現(xiàn)username前面會(huì)有一連串特殊字符,原因在于key值進(jìn)行了JdkSerializationRedisSerializer序列化,如果想去掉key值的特殊字符,需要對(duì)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;} }再次執(zhí)行看下效果:
@SpringBootTest class DemoApplicationTests {/**此處自動(dòng)裝配的RedisTemplate對(duì)象的序列化方式就是上面自定義的,即(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"));} }執(zhí)行單元測(cè)試,看下打印的日志效果:(沒(méi)有問(wèn)題)
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客戶(hù)端:發(fā)現(xiàn)usernameSerialize前面的特殊字符消失了,我們的更改序列化方式
生效啦,我們成功啦!!!!
但別高興的太早,有沒(méi)有發(fā)現(xiàn)一個(gè)新的問(wèn)題呢,usernameSerialize對(duì)應(yīng)的value值也變成有特殊字符啦!!!!別擔(dān)心,這是正?,F(xiàn)象,因?yàn)関alue值也是采用的JdkSerializationRedisSerializer進(jìn)行序列化的鴨!我們也可以采用上述指定序列化的方式進(jìn)行更改。
注意一點(diǎn):若采用JdkSerializationRedisSerializer序列化value、hashValue,則需要model中的類(lèi)實(shí)現(xiàn)Serializable接口,此外還有Jackson2JsonRedisSerializer序列化方式,使用它不需要model實(shí)現(xiàn)Serializable接口。
總結(jié)
以上是生活随笔為你收集整理的springboot中使用redis详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Springboot中使用jpa
- 下一篇: springboot使用定时器及发送邮件