目录
缓存管理
缓存是分布式系统中最重要的组件,主要解决数据库里的高并发访问。当用户访问量较大时,用户对高频热点数据的访问非常频繁,为提高服务器访问性能减少数据库压力,所以使用缓存。
Redis为什么要用缓存:
缓存主要是为了提升用户体验以及提高查询响应性能,也就是适应高并发,以及高性能的数据操作。
高性能:当用户第一次访问数据时,需要去硬盘中读取,如果是第二次或多次读取,但不改变的话,将数据放在缓存中,操作缓存就是直接操作内存,速度非常块。
高并发:一般向Mysql数据类的服务器每秒可执行的查询服务次数(QPS)在1w左右,但使用Redis缓存可以达到30+w左右,如果使用redis集群会更高。所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。进而,我们也就提高了系统整体的并发。
JAVA缓存核心接口
接口组成简介:
CachingProvider:可以创建、配置、获取、管理和控制CacheManager(缓存管理者),一个应用可以在运行期间访问多个CachingProvider.
CacheManager:可以创建、配置、获取、管理和控制唯一命名的Cache缓存,一个CacheManager仅被一个CacheProvider拥有。
Cache接口:是一个以Key为索引的值的临时储存数据结构。Cache 接口下 Spring 提供了各种 xxxCache 的实现,比如:RedisCache、EhCache、ConcurrentMapCache。
Entry:是一个存储在Cache中的key-value对。
Expiry:可以设置存储在Cache中的条目的有效期,一旦超过这个时间,条目尾为过期状态,则不可被访问更新删除。
组件结构图:
Spring抽象缓存
从3.1开始,Spring定义了Cache和CacheManager接口统一不同的缓存技术。
使用方式:
- 确定方法是否需要被缓存,确定缓存策略(缓存技术)
- 从缓存中读取之前的缓存数据
补充:
针对不同的缓存技术,需要实现不同的 CacheManager,Spring定义了如下的 cacheManger 实现:
1、SimpleCacheManager:使用简单的 Collection 来存储缓存,主要用于测试;
2、ConcurrentMapCacheManager:使用 ConcurrentMap 作为缓存技术(默认);
3、EhCacheCacheManager:使用 EhCache 作为缓存技术;
4、GuavaCacheManager:使用 google guava 的 GuavaCache 作为缓存技术;
5、RedisCacheManager:使用Redis作为缓存技术(spring-data-redis提供)。
Spring缓存主要注解:
@EnableCaching
该注解由Spring提供,配置在项目启动类上,用于开启注解的缓存支持
@EnableCaching
public class Springbootssm2Application {
public static void main(String[] args) {
SpringApplication.run(Springbootssm2Application.class, args);
}
}
@Cacheable
作用在拆类或方法上,通常用在数据查询方法上,用于对方法结果进行缓存存储
执行顺序:
- 进行缓存查询,如果为空则进行方法查询,将结果进行缓存
- 如果缓存中有数据,则不进行方法查询,直接使用缓存数据
属性:
1、cacheNames/value:用来指定缓存组件的名字,相当于给生成的键指定一个前缀,例如:@Cacheable(value = "brand"),在生成的键前面会添加brand::;
2、key:缓存数据时使用的 key,会拼接在cacheNames/value指定的缓存组件名后面,形成一个完整的键名,支持SPEL表达式;
3、keyGenerator:key 的生成器,可以自己指定 key 的生成器,通过这个生成器来生成 key;
4、cacheManager:指定要使用的缓存管理器;
5、condition:指定缓存数据的条件,默认为空,表示将缓存所有的调用情形。其值是通过SPEL表达式来指定的,当为 true 时表示进行缓存处理;当为 false 时表示不进行缓存处理;
6、unless:当 unless 指定的条件为 true ,方法的返回值就不会被缓存;
7、sync:是否使用异步模式。默认是方法执行完,以同步的方式将方法返回的结果存在缓存中。
@Cacheable(value = "brand", key = "#page.pageNum + '-' + #page.pageSize", condition = "#page.pageSize > 30")
@PostMapping("/allBrand")
public Result getAllBrand(@RequestBody Page page){
return brandService.getBrands(page);
}
/**
* 使用默认的配置和自定义的键生成策略
*/
@Cacheable(value = "c", keyGenerator = "myKeyGenerator")
@GetMapping("/brand")
public Result getBrand(@RequestParam("id") Long id){
return brandService.getBrand(id);
}
@CachePut
@CachePut也可以作用于类或方法,通常用在数据更新方法上。
与 @Cacheable 不同的是使用 @CachePut 标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
@CacheEvict
可以作用于类或方法,通常用在数据删除方法上,作用是删除缓存数据,该注释与@Cacheable基本相同,除此之外还有两个特殊属性
allEntries:表示是否清除指定缓存空间所有缓存数据,默认值为false,即默认只删除指定Key对应的缓存数据
beforeInvocation:表示是否再执行方法之前进行缓存清除,默认值为false。
@Caching
@Caching 注解可以在一个方法或者类上同时指定多个Spring Cache相关的注解。
三个属性:
cacheable、put 和 evict,分别用于指定@Cacheable、@CachePut 和 @CacheEvict。对于一个数据变动,更新多个缓存的场景,,可以通过 @Caching 来实现:
@Caching(cacheable = @Cacheable(cacheNames = "caching", key = "#age"), evict = @CacheEvict(cacheNames = "t4", key = "#age"))
public String caching(int age) {
return "caching: " + age + "-->" + UUID.randomUUID().toString();
}
上面这个就是组合操作:
从 caching::#age 缓存取数据,不存在时执行方法并写入缓存;
删除缓存 t4::#age。