概述
使用缓存可以提升系统性能,因为MySQL单机一般最多能够承受2000QPS,但是布式缓存Redis/Memcache能够支撑10W级别的QPS。所以合理的使用缓存能够提升系统的并发能力。同时,一般来说通过缓存取出去的延迟时间会更少,能够提升系统的性能。 缓存可以分为本地缓存、分布式缓存。
1. 本地缓存
适合单机应用,数据保存在服务器本地内存/硬盘中。
- 本地缓存框架:
# | guava | caffeine | ehcache |
|---|---|---|---|
| 是否开源 | Y | Y | Y |
| 优点 | 轻量级 | 轻量 | 重量 |
| JDK要求 | JDK5以上 | JDK7以上 | JDK4以上 |
| 缓存算法 | LRU | W-TinyLFU | LRU LFU FIFO |
| 持久化 | X | X | Y |
| 集群 | X | X | Y |
| Spring cache | X | Y | Y |
| 性能监控 | X | X | Y |
| 优点 | 轻量、免费 | 速度最快 | 功能最全面 |
2.分布式缓存
数据保存在缓存服务器中,通过构建缓存服务器集群来保证缓存服务的高可用。常见的分布式缓存有Reids和Memcache。
- 分布式缓存框架:
# | Redis | memcache |
|---|---|---|
| 性能 | TPS/QPS 10W+ | TPS/QPS 10W |
| 数据类型 | K-V、List、Map、Set | K-V |
| 内存限制 | 能 > 物理内存 | ≤ 物理内存大小 |
| 高可用 | 支持集群 | 支持集群 |
| 可靠性 | 支持AOF、快照 | — |
| 事务支持 | 支持 | 使用CAS保证一致性 |
| 缓存策略 | LRU、FIFO | LRU |
| Spring cache | 支持 | 支持 |
| 性能监控 | X | X |
Spring cache
使用 Spring cache 将缓存与业务解偶。 Spring cache 并不是一个缓存的实现方案,而是各种缓存方案的一个抽象,类似java.jdbc.*下接口的功能。这也是 Spring 框架最擅长干的事情,使用 Spring cache 的最大好处就是面向接口编程的最大好处,高度的“松耦合”,当项目中实际使用的缓存方案变化的时候,我们的接口都不是不用替换的。
Spring cache 可以说是一个基于 Spring AOP 实现的基于注解驱动的缓存技术。
其主要特点可以归纳如下:
- 通过少量的配置 annotation 注释即可使得既有代码支持缓存。
- 支持开箱即用 Out-Of-The-Box,即不用安装和部署额外第三方组件即可使用缓存。
- 支持 Spring Express Language,能使用对象的任何属性或者方法来定义缓存的 key 和 condition。
- 支持 AspectJ,并通过其实现任何方法的缓存支持。
- 支持自定义 key 和自定义缓存管理者,具有相当的灵活性和扩展性。
怎么使用 Spring cache呢? 很简单的,我们在引入 Spring cache 的jar包之后,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
在 Spring boot 类中添加注解@EnableCache就能够开启 Spring cache。
@EanbleCache
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
之后只需要在方法上写注解(Annotaion)就能完成对缓存的操作。
常用注解
| 注解 | 含义 |
|---|---|
| @Cachable | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存。 |
| @CachePut | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和@Cacheable不同的是,它每次都会触发真实方法的调用。 |
| @CacheEvict | 主要针对方法配置,能够根据一定的条件对缓存进行清空。 |
| @Chahing | |
| @CacheConfig |
@Cachable
value: 缓存的名称,在 spring 配置文件中定义,必须指定至少一个。 e.g.@Cacheable(value=”mycache”) @Cacheable(value={”cache1”,”cache2”}key: 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合。 e.g.@Cacheable(value=”testcache”,key=”#userName”)condition: 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存。 e.g.@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
@CachePut
value: 缓存的名称,在 spring 配置文件中定义,必须指定至少一个。 e.g.@CachePut(value=”mycache”) @CachePut(value={”cache1”,”cache2”}key: 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合。 e.g.@CachePut(value=”testcache”,key=”#userName”)condition: 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存。 e.g.@CachePut(value=”testcache”,condition=”#userName.length()>2”)
@CacheEvict
key: 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合。 e.g.@CachEvict(value=”mycache”) @CachEvict(value={”cache1”,”cache2”}value: 缓存的名称,在 spring 配置文件中定义,必须指定至少一个。 e.g.@CachEvict(value=”testcache”,key=”#userName”)condition: 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存。 e.g.@CachEvict(value=”testcache”, condition=”#userName.length()>2”)allEntries: 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存。 e.g.@CachEvict(value=”testcache”,allEntries=true)beforeInvocation: 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存。 e.g.@CachEvict(value=”testcache”,beforeInvocation=true)
引用参考: