当前位置: 首页 > 科技观察

SpringBoot集成Redis实现缓存操作_0

时间:2023-03-15 15:19:17 科技观察

1.缓存的应用场景2.更新缓存的策略3.运行springboot-mybatis-redis项目案例4.springboot-mybatis-redis项目代码配置详解运行环境:Mac操作系统10.12。xJDK8+Redis3.2.8SpringBoot1.5.1.RELEASE一、缓存的应用场景什么是缓存?在互联网场景下,尤其是2C端大流量场景下,需要将一些经常展示、不经常变化的数据存放在访问速度较快的地方。缓存是内存。在技??术选型上,Redis常被用作缓存数据库。缓存主要是获取资源的一个关键环节,方便性能优化。Redis是一个高性能的键值数据库。GitHub地址:https://github.com/antirez/redis。Github是这样描述的:Redis是一个持久存在于磁盘上的内存数据库。数据模型是键值对,但支持许多不同类型的值:字符串、列表、集合、有序集合、哈希、HyperLogLogs、位图。缓存有哪些应用场景?例如,在常见的电商场景中,根据商品ID获取商品信息时,店铺信息和商品详情信息可以缓存在Redis中,直接从Redis中获取。减少了数据库查询的数量。但是会有一个新的问题,就是如何更新缓存呢?这就是我下面要讲的。2.更新缓存策略缓存更新有四种方式:Cacheaside、Readthrough、Writethrough、Writebehindcaching。这里我们使用的是CacheAside策略,从三个维度:(摘自老鼠大叔的博客)Invalidation:应用先从缓存中取数据,如果没有,则从数据库中取数据,成功后放入缓存。***:应用程序从缓存中取数据,取完后返回。update:先将数据存入数据库,成功后再使缓存失效。大致流程如下:获取商品详情示例a.从商品缓存中获取商品详情,如果存在则返回获取缓存数据并返回。b.如果不存在,请从项目数据库中获取。获取成功后,将数据存入Cache。那么下次获取商品详情时,就可以从Cache中获取商品详情数据。C。在商品DB中成功更新或删除商品详情后,从缓存中删除对应的商品详情缓存。3、运行springboot-mybatis-redis项目案例gitclone下载项目springboot-learning-example。项目地址见GitHub-https://github.com/JeffLi1993/springboot-learning-example。下面开始运行项目步骤(QuickStart):1.数据库和Redis准备a.创建数据库springbootdb:CREATEDATABASEspringbootdbb。创建表city:(因为我喜欢徒步)DROPTABLEIFEXISTS`city`;CREATETABLE`city`(`id`int(10)unsignedNOTNULLAUTO_INCREMENTCOMMENT'城市编号',`province_id`int(10)unsignedNOTNULLCOMMENT'省编号',`city_name`varchar(25)DEFAULTNULLCOMMENT'城市名称',`description`varchar(25)DEFAULTNULLCOMMENT'description',PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8;C。插入数据INSERTcityVALUES(1,1,'温岭市','BYSocket的家在温岭。');d.Redis的本地安装可以参考写文章《 Redis 安装 》http://www.bysocket.com/?p=9172。springboot-mybatis-redis项目结构介绍springboot-mybatis-redis项目结构如下如图:org.spring.springboot.controller-控制器层org.spring.springboot.dao-数据操作层DAOorg.spring.springboot.domain-实体类org.spring.springboot.service-业务逻辑层Application-应用启动类application.properties-应用配置文件,应用启动会自动读取配置3.更改数据库配置打开application.properties文件,并修改相应的数据源配置,如数据源地址、账号、密码等(如果不是使用MySQL,请自行添加连接驱动pom,然后修改驱动名称配置。)4.编译该项目在项目根目录下springboot-learning-example,运行maven命令:mvncleaninstall5。运行项目右键运行springboot-mybatis-redis项目Application应用启动类的主要功能。项目运行成功后,这是一个HTTPOVERJSON服务项目。所以使用postman工具,可以通过如下操作获取城市信息GEThttp://127.0.0.1:8080/api/city/1,根据ID重新请求。如果你获取了城市信息,你会发现耗时的数据获取要快很多。服务器控制台输出的日志:2017-04-1318:29:00.273INFO13038---[nio-8080-exec-1]o.s.s.service.impl.CityServiceImpl:CityServiceImpl.findCityById():cityinsertioncache>>City{id=12,provinceId=3,cityName='三亚',description='水好天蓝'}2017-04-1318:29:03.145INFO13038---[nio-8080-exec-2]o.s.s.service.impl.CityServiceImpl:CityServiceImpl.findCityById():从缓存中获取城市>>City{id=12,provinceId=3,cityName='三亚',description='水好,天蓝'}可见,第一次是从数据库DB中获取数据,插入到缓存中,第二次直接从缓存中取数据。更新城市信息PUThttp://127.0.0.1:8080/api/city删除城市信息DELETEhttp://127.0.0.1:8080/api/city/2在这两个操作中,如果缓存中有相应的数据,然后删除缓存。服务器控制台输出的日志:12017-04-1318:29:52.248INFO13038---[nio-8080-exec-9]o.s.s.service.impl.CityServiceImpl:CityServiceImpl.deleteCity():DeletethecityIDfromthecache>>124.springboot-mybatis-redis项目代码配置详解这里强烈推荐注解的方式实现对象缓存。不过这里是为了更好的说明缓存更新策略。下面说一下工程代码的实现。pom.xml依赖配置:4.0.0springbootspringboot-mybatis-redis0.0.1-SNAPSHOTspringboot-mybatis-redis::整合Mybatis并使用Redis作为存档org.springframework.bootspring-boot-starter-parent1.5.1.RELEASE1.2.05.1。391.3.2.RELEASEorg.springframework.bootspring-boot-starter-redis${spring-boot-starter-redis-version}groupId>org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-testtestorg.mybatis.spring.启动mybatis-spring-boot-starter${mybatis-spring-boot}mysqlmysql-connector-java${mysql-connector}junitjunit4.12包括SpringBootReids依赖、MySQL依赖和Mybatis依赖应用application.properties中的配置文件,添加Redis相关配置##数据源配置spring.datasource.url=jdbc:mysql://localhost:3306/springbootdb?useUnicode=true&characterEncoding=utf8spring.datasource.username=rootspring.datasource。password=123456spring.datasource.driver-class-name=com.mysql.jdbc.Driver##Mybatis配置mybatis.typeAliasesPackage=org.spring.springboot.domainmybatis.mapperLocations=classpath:mapper/*.xml##Redis配置##Redis数据库索引(默认为0)spring.redis.database=0##Redis服务器地址spring.redis.host=127.0.0.1##Redis服务器连接端口spring.redis.port=6379##Redis服务器连接密码(默认为空)spring.redis.password=##连接池***连接数(使用负值表示不限制)spring.redis.pool.max-active=8##连接池***阻塞等待时间(使用负值表示没有限制)spring.redis.pool.max-wait=-1##连接中的***空闲连接poolspring.redis.pool.max-idle=8##连接池中最小空闲连接spring.redis.pool.min-idle=0##连接超时时间(毫秒)spring.redis.timeout=0详细解释可以参考评论。对应的配置类:org.springframework.boot.autoconfigure.data.redis.RedisPropertiesCityRestController控制层依然是Restful风格,详见《Springboot 实现 Restful 服务,基于 HTTP / JSON 传输》。http://www.bysocket.com/?p=1627领域对象City必须实现序列化,因为该对象需要序列化后存储到Redis中。如果没有实现Serializable,控制台会弹出如下异常:Serializablejava.lang.IllegalArgumentException:DefaultSerializerrequiresaSerializablepayloadbutreceivedanobjectoftypeCity.javacityobject:packageorg.spring.springboot.domain;importjava.io.Serializable;/***cityentityclass**Createdbysocketon07/02/2017.*/publicclassCityimplementsSerializable{privatestaticfinallongserialVersionUID=-1L;/***城市编号*/privateLongid;/***省编号*/privateLongprovinceId;/***城市名称*/privateStringcityName;/***描述*/privateStringdescription;publicLonggetId(){returnid;}publicvoidsetId(Longid){this.id=id;}publicLonggetProvinceId(){returnprovinceId;}publicvoidsetProvinceId(LongprovinceId){this.provinceId=provinceId;}publicStringgetCityName(){returnNameturncityName;}publicStringgetCityName(){returnNameturncityName;){this.cityName=cityName;}publicStringgetDescription(){returndescription;}publicvoidsetDescription(Stringdescription){this.description=description;}@OverridepublicStringtoString(){return"City{"+"id="+id+",provinceId="+provinceId+",cityName='"+cityName+'\''+",description='"+description+'\''+'}';}}如果需要自定义序列化实现,只需实现RedisSerializer接口来实现即可,然后使用RedisTemplate.setValueSerializer方法设置你实现的序列化实现主要是城市业务逻辑实现类CityServiceImpl.java:packageorg.spring.springboot.service.impl;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.spring.springboot.dao.CityDao;importorg.spring.springboot.domainimportorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.data.redis.core.ValueOperations;importorg。springframework.stereotype.Service;importjava.util.List;importjava.util.concurrent.TimeUnit;/***城市业务逻辑实现类*

*Createdbysocketon07/02/2017.*/@ServicepublicclassCityServiceImplimplementsCityService{privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(CityServiceImpl.class);@AutowiredprivateCityDaocityDao;@AutowiredprivateRedisTemplateredisTemplate;/***获取城市逻辑:*如果缓存存在,从缓存中获取城市信息*如果缓存不存在,获取城市从DB中获取信息,然后插入缓存*/publicCityfindCityById(Longid){//从缓存中获取城市城市信息Stringkey="city_"+id;ValueOperationsoperations=redisTemplate.opsForValue();//缓存存在booleanhasKey=redisTemplate.hasKey(key);if(hasKey){Citycity=operations.get(key);LOGGER.info("CityServiceImpl.findCityById():从缓存中获取城市>>"+city.toString());returncity;}//从DB中获取城市信息Citycity=cityDao.findById(id);//插入缓存操作.set(key,city,10,TimeUnit.SECONDS);LOGGER.info("CityServiceImpl.findCityById():城市插入缓存>>"+city.toString());returncity;}@OverridepublicLongsaveCity(Citycity){returncityDao.saveCity(city);}/***更新城市逻辑:*如果缓存存在则删除*如果缓存不存在则不操作*/@OverridepublicLongupdateCity(Citycity){Longret=cityDao.updateCity(city);//缓存存在,删除缓存Stringkey="city_"+city.getId();booleanhasKey=redisTemplate.hasKey(key);if(hasKey){redisTemplate.delete(key);LOGGER.info("CityServiceImpl.updateCity():从缓存中删除城市>>"+city.toString());}returnret;}@OverridepublicLongdeleteCity(Longid){Longret=cityDao.deleteCity(id);//缓存存在,删除缓存Stringkey="city_"+id;booleanhasKey=redisTemplate.hasKey(key);if(hasKey){redisTemplate.delete(key);LOGGER.info("CityServiceImpl.deleteCity():from缓存删除城市ID>>"+id);}returnret;}}这里首先注入RedisTemplate对象,关联Spring的JdbcTemplate。RedisTemplate封装了RedisConnection,具有连接管理、序列化、Redis操作等功能。String还有一个支持对象StringRedisTemplate。Redis操作视图接口类使用ValueOperations,对应RedisString/Value操作。还有其他操作视图,ListOperations、SetOperations、ZSetOperations和HashOperations。ValueOperations插入缓存可以设置失效时间,这里设置的失效时间为10s。回到更新缓存的逻辑a。findCityById获取城市逻辑:如果缓存存在,则从缓存中获取城市信息如果缓存不存在,则从DB中获取城市信息,然后插入缓存b。deleteCitydelete/updateCity更新城市逻辑:如果缓存存在,则删除。如果缓存不存在,其他不明白,可以gitclone下载项目springboot-learning-example。项目代码注释非常详细。https://github.com/JeffLi1993/springboot-learning-example。五、小结本文涉及到SpringBoot在使用Redis缓存时,一是缓存对象需要序列化,二是缓存更新策略如何。摘要:原创出处www.bysocket.com《MasonBYSocket》欢迎转载,保留摘要,谢谢!