为什么要进行缓存优化?
问题说明:
如果项目移动端的用户比较多,都去请求移动端系统,都要进行点餐操作时,请求就会都压到数据库(DB)上。
造成的后果就是:用户数量多,系统访问量大。频繁访问数据库,系统性能下降,用户体验差。。(直观的感受就是,页面加载速度比较慢)
如何解决?
通过缓存来解决。
(即在用户点击移动端时,系统并不是直接查询数据库,而是先看缓存里面有没有相应的数据。有数据的话,就不用再查询数据库,直接把数据返回给页面即可)因为很多缓存产品,本质上就是内存操作,相对于数据库查询操作来说,访问速度要快上很多。
利用缓存,从而提高系统的响应性能,提高用户体验度。这里就需要Redis的参与了
Spring Cache框架
Spring Cache介绍
Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就可以实现缓存功能。
Spring Cache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。
CacheManager是Spring提供的各种缓存技术抽象接口。
针对不同的缓存技术需要实现不同的CacheManager:
CacheManager | 描述 |
EhCacheCacheManager | 使用EhCache作为缓存技术 |
GuavaCacheManager | 使用Google的GuavaCache作为缓存技术 |
RedisCacheManager | 使用Redis作为缓存技术 |
Spring Cache常用注解
注解 | 说明 |
@EnableCaching | 开启缓存注解功能(一般放在启动类上) |
@Cacheable | 在方法执行前Spring先检查缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中。(一般放在方法上) |
@CachePut | 将方法的返回值放到缓存中(提供数据缓存,一般也是放在方法上) |
@CacheEvict | 将一条或多条数据从缓存中删除(提供缓存删除,也一般是在方法上) |
在Spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。
例如,使用Redis作为缓存技术,只需要导入Spring data Redis的maven坐标即可。
缓存实现思路:
比如移动端的套餐查看功能,对应的服务端方法为对应Controller中的list方法,此方法会根据前端提交的查询条件进行数据库查询操作。
在高并发的情况下,频繁查询数据库会导致系统性能下降,服务端响应时间增长。现在需要对此方法进行缓存优化,提高系统的性能。
具体思路如下:
1、导入Spring Cache和Redis相关maven坐标
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2、在application.yml中配置缓存数据的过期时间
cache:
resis:
time-to-live: 1800000 #设置缓存数据的过期时间 单位ms
3、在启动类上加入@EnableCaching注解,开启缓存注解功能
4、在对应Controller的list方法上加入@Cacheable注解
@GetMapping("/list")
@Cacheable(value = "setmealCache",key = "#setmeal.categoryId + '_' + #setmeal.status")
public R<List<Setmeal>> list(Setmeal setmeal) {
此时运行之后,发现前端页面点击套餐,会报500错误。回到控制台看到
提示,默认的序列化器结果需要实现序列化接口,而返回的R这个类还没有。所以需要让R实现序列化接口,否则无法实现缓存。对R这个对象,加上实现接口:
5、在对应Controller的save和delete方法上加入@CacheEvict注解