首页>>后端>>SpringBoot->SpringBoot整合Redis,封装RedisUtils

SpringBoot整合Redis,封装RedisUtils

时间:2023-11-29 本站 点击:0

Redis

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

Redis 是目前业界使用最广泛的内存数据存储。相比 Memcached,Redis 支持更丰富的数据结构,例如 hashes, lists, sets 等,同时支持数据持久化。

除此之外,Redis 还提供一些类数据库的特性,比如事务,HA,主从库。可以说 Redis 兼具了缓存系统和数据库的一些特性,因此有着丰富的应用场景。本文介绍 Redis 在 Spring Boot 中两个典型的应用场景。

Redis API 介绍

Spring Boot 提供的 Redis API 分为 高阶 API 和 低阶 API,高阶 API 是经过一定封装后的 API,而低阶 API 的使用和直接使用 Redis 的命令差不多。

高阶 API 提供了两个类可以供我们使用,分别是 RedisTemplateStringRedisTemplate。StringRedisTemplate 继承自 RedisTemplate,StringRedisTemplate 的序列化方式与 RedisTemplate 的序列化的方式不同。具体在使用上的差别不是特别明显,但是数据在存储到 Redis 中的时候,因为序列化方式的不同,会有一定的差别。

低阶 API 其实也是通过 RedisTemplate 或 StringRedisTemplate 来进行获取。低阶 API 的方法和 Redis 的命令差不多。

Redis序列化

1、什么是序列化和反序列化

序列化:将对象写到IO流中

反序列化:从IO流中恢复对象

序列化的意义:序列化机制允许将实现序列化的Java对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。

2、只需要配置一下,就可以解决刚才出现的问题,但是这么多序列化的手段如何挑选呢,我比较好奇,所以我又稍微深挖了一下:
/***Description:Redis配置*/@ConfigurationpublicclassMyRedisConfig{/***redisTemplate配置*序列化的几种方式:*OxmSerializer*ByteArrayRedisSerializer*GenericJackson2JsonRedisSerializer*GenericToStringSerializer*StringRedisSerializer*JdkSerializationRedisSerializer*Jackson2JsonRedisSerializer*@paramredisConnectionFactoryredis连接工厂*@returnRedisTemplate*/@BeanpublicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactoryredisConnectionFactory){RedisTemplate<Object,Object>template=newRedisTemplate<>();//配置连接工厂template.setConnectionFactory(redisConnectionFactory);//设置key的序列化方式template.setKeySerializer(newStringRedisSerializer());//设置value的序列化方式template.setValueSerializer(newJackson2JsonRedisSerializer<Object>(Object.class));returntemplate;}}
名称说明ByteArrayRedisSerializer数组序列化GenericJackson2JsonRedisSerializer使用Jackson进行序列化GenericToStringSerializer将对象泛化成字符串并序列化,和StringRedisSerializer差不多Jackson2JsonRedisSerializer使用Jackson序列化对象为jsonJdkSerializationRedisSerializerjdk自带的序列化方式,需要实现Serializable接口OxmSerializer用xml格式存储StringRedisSerializer简单的字符串序列化
3、比较几种常见序列化手段的差异
@SpringBootTestclassCacheApplicationTests{/***测试几种序列化手段的效率*/@Testvoidtest(){Useruser=newUser();user.setId(1);user.setUsername("张三");user.setPassword("123");List<Object>list=newArrayList<>();for(inti=0;i<2000;i++){list.add(user);}//使用GenericJackson2JsonRedisSerializer做序列化(效率太低,不推荐使用)GenericJackson2JsonRedisSerializerg2=newGenericJackson2JsonRedisSerializer();longg2s=System.currentTimeMillis();byte[]byteG2=g2.serialize(list);longg2l=System.currentTimeMillis();System.out.println("GenericJackson2JsonRedisSerializer序列化消耗的时间:"+(g2l-g2s)+"ms,序列化之后的长度:"+byteG2.length);g2.deserialize(byteG2);System.out.println("GenericJackson2JsonRedisSerializer反序列化的时间:"+(System.currentTimeMillis()-g2l)+"ms");//使用GenericToStringSerializer做序列化(和StringRedisSerializer差不多,效率没有StringRedisSerializer高,不推荐使用)GenericToStringSerializerg=newGenericToStringSerializer(Object.class);longgs=System.currentTimeMillis();byte[]byteG=g.serialize(list.toString());longgl=System.currentTimeMillis();System.out.println("GenericToStringSerializer序列化消耗的时间:"+(gl-gs)+"ms,序列化之后的长度:"+byteG.length);g.deserialize(byteG);System.out.println("GenericToStringSerializer反序列化的时间:"+(System.currentTimeMillis()-gl)+"ms");//使用Jackson2JsonRedisSerializer做序列化(效率高,适合value值的序列化)Jackson2JsonRedisSerializerj2=newJackson2JsonRedisSerializer(Object.class);longj2s=System.currentTimeMillis();byte[]byteJ2=j2.serialize(list);longj2l=System.currentTimeMillis();System.out.println("Jackson2JsonRedisSerializer序列化消耗的时间:"+(j2l-j2s)+"ms,序列化之后的长度:"+byteJ2.length);j2.deserialize(byteJ2);System.out.println("Jackson2JsonRedisSerializer反序列化的时间:"+(System.currentTimeMillis()-j2l)+"ms");//使用JdkSerializationRedisSerializer,实体类必须实现序列化接口(不推荐使用)JdkSerializationRedisSerializerj=newJdkSerializationRedisSerializer();longjs=System.currentTimeMillis();byte[]byteJ=j.serialize(list);longjl=System.currentTimeMillis();System.out.println("JdkSerializationRedisSerializer序列化消耗的时间:"+(jl-js)+"ms,序列化之后的长度:"+byteJ.length);j.deserialize(byteJ);System.out.println("JdkSerializationRedisSerializer反序列化的时间:"+(System.currentTimeMillis()-jl)+"ms");//使用StringRedisSerializer做序列化(效率非常的高,但是比较占空间,只能对字符串序列化,适合key值的序列化)StringRedisSerializers=newStringRedisSerializer();longss=System.currentTimeMillis();byte[]byteS=s.serialize(list.toString());longsl=System.currentTimeMillis();System.out.println("StringRedisSerializer序列化消耗的时间:"+(sl-ss)+"ms,序列化之后的长度:"+byteS.length);s.deserialize(byteS);System.out.println("StringRedisSerializer反序列化的时间:"+(System.currentTimeMillis()-sl)+"ms");//使用FastJson做序列化,这个表现为什么这么差我也不是很明白FastJsonRedisSerializer<Object>f=newFastJsonRedisSerializer<>(Object.class);longfs=System.currentTimeMillis();byte[]byteF=f.serialize(list);longfl=System.currentTimeMillis();System.out.println("FastJsonRedisSerializer序列化消耗的时间:"+(fl-fs)+"ms,序列化之后的长度:"+byteF.length);f.deserialize(byteF);System.out.println("FastJsonRedisSerializer反序列化的时间:"+(System.currentTimeMillis()-fl)+"ms");//使用FastJson(效率高,序列化后占空间也很小,推荐使用)GenericFastJsonRedisSerializergf=newGenericFastJsonRedisSerializer();longgfs=System.currentTimeMillis();byte[]byteGf=gf.serialize(list);longgfl=System.currentTimeMillis();System.out.println("GenericFastJsonRedisSerializer序列化消耗的时间:"+(gfl-gfs)+"ms,序列化之后的长度:"+byteGf.length);gf.deserialize(byteGf);System.out.println("GenericFastJsonRedisSerializer反序列化的时间:"+(System.currentTimeMillis()-gfl)+"ms");}}
4、总结
名称序列化效率反序列化效率占用空间是否推荐使用StringRedisSerializer很高很高高推荐给key进行序列化Jackson2JsonRedisSerializer高较高偏高推荐给value进行序列化GenericFastJsonRedisSerializer高较低较低推荐给value进行序列化
5、附上Redis序列化配置文件
/***@Description:Redis配置*/@ConfigurationpublicclassMyRedisConfig{/***redisTemplate配置*@paramredisConnectionFactoryredis连接工厂*@returnRedisTemplate*/@BeanpublicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactoryredisConnectionFactory){RedisTemplate<Object,Object>template=newRedisTemplate<>();//配置连接工厂template.setConnectionFactory(redisConnectionFactory);//配置key的序列化方式template.setKeySerializer(newStringRedisSerializer());//使用Jackson2JsonRedisSerializer配置value的序列化方式template.setValueSerializer(newJackson2JsonRedisSerializer<>(Object.class));//使用FastJson配置value的序列化方式//template.setValueSerializer(newGenericFastJsonRedisSerializer());returntemplate;}}

封装RedisUtils工具类

引入Redis依赖
<!--SpringBoot与Redis整合依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
设置Redis的Template ——> RedisConfig.java
/***@Description:Redis配置类*/@ConfigurationpublicclassRedisConfig{publicRedisTemplate<String,String>redisTemplate(RedisConnectionFactoryfactory){RedisTemplate<String,String>redisTemplate=newRedisTemplate<>();RedisSerializer<String>redisSerializer=newStringRedisSerializer();redisTemplate.setConnectionFactory(factory);//key序列化redisTemplate.setKeySerializer(redisSerializer);//value序列化redisTemplate.setValueSerializer(redisSerializer);//keyhashmap序列化redisTemplate.setHashKeySerializer(redisSerializer);//valuehashmap序列化redisTemplate.setHashValueSerializer(redisSerializer);returnredisTemplate;}}
设置连接信息
#Redis#连接的那个数据库spring.redis.database=0#redis服务的ip地址spring.redis.host=127.0.0.1#redis端口号spring.redis.port=6379#redis的密码,没设置过密码,可为空spring.redis.password=ycfxhsw
Redis工具类
/***Redis工具类*/@ServicepublicclassRedisUtils{@AutowiredprivateRedisTemplateredisTemplate;privatestaticdoublesize=Math.pow(2,32);/***写入缓存*@paramkey*@paramoffset*@paramisShow*@returnresult*/publicbooleansetBit(Stringkey,longoffset,booleanisShow){booleanresult=false;try{ValueOperations<Serializable,Object>operations=redisTemplate.opsForValue();operations.setBit(key,offset,isShow);result=true;}catch(Exceptione){e.printStackTrace();}returnresult;}/***写入缓存*@paramkey*@paramoffset*@returnresult*/publicbooleangetBit(Stringkey,longoffset){booleanresult=false;try{ValueOperations<Serializable,Object>operations=redisTemplate.opsForValue();result=operations.getBit(key,offset);}catch(Exceptione){e.printStackTrace();}returnresult;}/***写入缓存*@paramkey*@paramvalue*@return*/publicbooleanset(finalStringkey,Objectvalue){booleanresult=false;try{ValueOperations<Serializable,Object>operations=redisTemplate.opsForValue();operations.set(key,value);result=true;}catch(Exceptione){e.printStackTrace();}returnresult;}/***写入缓存设置时效时间*@paramkey*@paramvalue*@return*/publicbooleanset(finalStringkey,Objectvalue,LongexpireTime){booleanresult=false;try{ValueOperations<Serializable,Object>operations=redisTemplate.opsForValue();operations.set(key,value);redisTemplate.expire(key,expireTime,TimeUnit.SECONDS);result=true;}catch(Exceptione){e.printStackTrace();}returnresult;}/***批量删除对应的value*@paramkeys*/publicvoidremove(finalString...keys){for(Stringkey:keys){remove(key);}}/***删除对应的value*@paramkey*/publicvoidremove(finalStringkey){if(exists(key)){redisTemplate.delete(key);}}/***判断缓存中是否有对应的value*@paramkey*@return*/publicbooleanexists(finalStringkey){returnredisTemplate.hasKey(key);}/***读取缓存*@paramkey*@return*/publicObjectget(finalStringkey){Objectresult=null;ValueOperations<Serializable,Object>operations=redisTemplate.opsForValue();result=operations.get(key);returnresult;}/***哈希添加*@paramkey*@paramhashKey*@paramvalue*/publicvoidhmSet(Stringkey,ObjecthashKey,Objectvalue){HashOperations<String,Object,Object>hash=redisTemplate.opsForHash();hash.put(key,hashKey,value);}/***哈希获取数据*@paramkey*@paramhashKey*@return*/publicObjecthmGet(Stringkey,ObjecthashKey){HashOperations<String,Object,Object>hash=redisTemplate.opsForHash();returnhash.get(key,hashKey);}/***列表添加*@paramk*@paramv*/publicvoidlPush(Stringk,Objectv){ListOperations<String,Object>list=redisTemplate.opsForList();list.rightPush(k,v);}/***列表获取*@paramk*@paraml*@paraml1*@return*/publicList<Object>lRange(Stringk,longl,longl1){ListOperations<String,Object>list=redisTemplate.opsForList();returnlist.range(k,l,l1);}/***集合添加*@paramkey*@paramvalue*/publicvoidadd(Stringkey,Objectvalue){SetOperations<String,Object>set=redisTemplate.opsForSet();set.add(key,value);}/***集合获取*@paramkey*@return*/publicSet<Object>setMembers(Stringkey){SetOperations<String,Object>set=redisTemplate.opsForSet();returnset.members(key);}/***有序集合添加*@paramkey*@paramvalue*@paramscoure*/publicvoidzAdd(Stringkey,Objectvalue,doublescoure){ZSetOperations<String,Object>zset=redisTemplate.opsForZSet();zset.add(key,value,scoure);}/***有序集合获取*@paramkey*@paramscoure*@paramscoure1*@return*/publicSet<Object>rangeByScore(Stringkey,doublescoure,doublescoure1){ZSetOperations<String,Object>zset=redisTemplate.opsForZSet();redisTemplate.opsForValue();returnzset.rangeByScore(key,scoure,scoure1);}/***第一次加载的时候将数据加载到redis中*@paramname*/publicvoidsaveDataToRedis(Stringname){doubleindex=Math.abs(name.hashCode()%size);longindexLong=newDouble(index).longValue();booleanavailableUsers=setBit("availableUsers",indexLong,true);}/***第一次加载的时候将数据加载到redis中*@paramname*@return*/publicbooleangetDataToRedis(Stringname){doubleindex=Math.abs(name.hashCode()%size);longindexLong=newDouble(index).longValue();returngetBit("availableUsers",indexLong);}/***有序集合获取排名*@paramkey集合名称*@paramvalue值*/publicLongzRank(Stringkey,Objectvalue){ZSetOperations<String,Object>zset=redisTemplate.opsForZSet();returnzset.rank(key,value);}/***有序集合获取排名*@paramkey*/publicSet<ZSetOperations.TypedTuple<Object>>zRankWithScore(Stringkey,longstart,longend){ZSetOperations<String,Object>zset=redisTemplate.opsForZSet();Set<ZSetOperations.TypedTuple<Object>>ret=zset.rangeWithScores(key,start,end);returnret;}/***有序集合添加*@paramkey*@paramvalue*/publicDoublezSetScore(Stringkey,Objectvalue){ZSetOperations<String,Object>zset=redisTemplate.opsForZSet();returnzset.score(key,value);}/***有序集合添加分数*@paramkey*@paramvalue*@paramscoure*/publicvoidincrementScore(Stringkey,Objectvalue,doublescoure){ZSetOperations<String,Object>zset=redisTemplate.opsForZSet();zset.incrementScore(key,value,scoure);}/***有序集合获取排名*@paramkey*/publicSet<ZSetOperations.TypedTuple<Object>>reverseZRankWithScore(Stringkey,longstart,longend){ZSetOperations<String,Object>zset=redisTemplate.opsForZSet();Set<ZSetOperations.TypedTuple<Object>>ret=zset.reverseRangeByScoreWithScores(key,start,end);returnret;}/***有序集合获取排名*@paramkey*/publicSet<ZSetOperations.TypedTuple<Object>>reverseZRankWithRank(Stringkey,longstart,longend){ZSetOperations<String,Object>zset=redisTemplate.opsForZSet();Set<ZSetOperations.TypedTuple<Object>>ret=zset.reverseRangeWithScores(key,start,end);returnret;}}
测试
@RestControllerpublicclassRedisController{@AutowiredprivateRedisUtilsredisUtils;@RequestMapping("setAndGet")publicStringtest(Stringk,Stringv){redisUtils.set(k,v);return(String)redisUtils.get(k);}}

作者:Dynasty


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/SpringBoot/368.html