笔者之前做商城项目时,做过商城首页的商品分类功能 。当时考虑分类是放在商城首页,以后流量大,而且不经常变动,为了提升首页访问速度,我考虑使用缓存 。对于JAVA开发而言,首先的缓存当然是redis 。
优化前系统流程图:
文章插图
我们从图中可以看到,分类功能分为生成分类数据 和 获取分类数据两个流程,生成分类数据流程是有个JOB每隔5分钟执行一次,从MySQL中获取分类数据封装成首页需要展示的分类数据结构,然后保存到redis中 。获取分类数据流程是商城首页调用分类接口,接口先从redis中获取数据,如果没有获取到再从mysql中获取 。
一般情况下从redis就都能获取数据,因为相应的key是没有设置过期时间的,数据会一直都存在 。以防万一,我们做了一次兜底,如果获取不到数据,就会从mysql中获取 。
本以为万事大吉,后来,在系统上线之前,测试对商城首页做了一次性能压测,发现qps是100多,一直上不去 。我们仔细分析了一下原因,发现了两个主要的优化点:去掉多余的接口日志打印 和 分类接口引入redis cache做一次二级缓存 。日志打印我在这里就不多说了,不是本文的重点,我们重点说一下redis cache 。
优化后的系统流程图:
文章插图
我们看到,其他的流程都没有变,只是在获取分类接口中增加了先从spring cache中获取分类数据的功能,如果获取不到再从redis中获取,再获取不到才从mysql中获取 。
经过这样一次小小的调整,再重新压测接口,性能一下子提升了N倍,满足了业务要求 。如此美妙的一次优化经验,有必要跟大家分析一下 。
我将从以下几个方面给大家分享一下spring cache 。
- 基本用法
- 项目中如何使用
- 工作原理
- @EnableCaching:开启缓存功能
- @Cacheable:获取缓存
- @CachePut:更新缓存
- @CacheEvict:删除缓存
- @Caching:组合定义多种缓存功能
- @CacheConfig:定义公共设置,位于类之上
@EnableCaching注解是缓存的开关,如果要使用缓存功能,就必要打开这个开关,这个注解可以定义在Configuration类或者springboot的启动类上面 。
@Cacheable、@CachePut、@CacheEvict 这三个注解的用户差不多,定义在需要缓存的具体类或方法上面 。
@Cacheable(key="'id:'+#id")public User getUser(int id) {return userService.getUserById(id);}@CachePut(key="'id:'+#user.id")public User insertUser(User user) {userService.insertUser(user);return user;}@CacheEvict(key="'id:'+#id")public int deleteUserById(int id) {userService.deleteUserById(id);return id;}
需要注意的是@Caching注解跟另外三个注解不同,它可以组合另外三种注解,自定义新注解 。@Caching(cacheable = {@Cacheable(/*value = https://www.isolves.com/it/cxkf/kj/2020-09-27/"emp",*/key = "#lastName")put = {@CachePut(/*value = "emp",*/key = "#result.id")})public Employee getEmpByLastName(String lastName){returnemployeeMApper.getEmpByLastName(lastName);}
@CacheConfig一般定义在配置类上面,可以抽取缓存的公共配置,可以定义这个类全局的缓存名称,其他的缓存方法就可以不配置缓存名称了 。
@CacheConfig(cacheNames = "emp")@Servicepublic class EmployeeService
二、项目中如何使用- 引入caffeine的相关jar包我们这里使用caffeine,而非guava,因为Spring Boot 2.0中取代了guava
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.6.0</version></dependency>
2. 配置CacheManager,开启EnableCaching@Configuration@EnableCachingpublic class CacheConfig {@Beanpublic CacheManager cacheManager(){CaffeineCacheManager cacheManager = new CaffeineCacheManager();//Caffeine配置Caffeine<Object, Object> caffeine = Caffeine.newBuilder()//最后一次写入后经过固定时间过期.expireAfterWrite(10, TimeUnit.SECONDS)//缓存的最大条数.maximumSize(1000);cacheManager.setCaffeine(caffeine);return cacheManager;}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 如何使用软路由实现宽带加速,免费让300M宽带变600M
- 使用 Python 自动发送 QQ 消息
- 人人都能掌握的Chrome使用技巧
- Android Hawk框架使用介绍
- 使用Docker来构建、运行、发布微服务
- 使用Excel来制作文件管理目录
- RFM模型升级,使用Excel完成全自动分析
- Springboot 实现数据库备份还原
- 组策略 WindowsServer2008的使用详解
- Docker下使用disconf:细说demo开发