SpringCache模块
Spring Cache是Spring针对Spring应用,给出的一整套应用缓存解决方案。
Spring Cache本身并不提供缓存实现,而是通过统一的接口和代码规范,配置、注解等使你可以在Spring应用中使用各种Cache,而不用太关心Cache的细节。通过Spring Cache ,你可以方便的使用
各种缓存实现,包括ConcurrentMap,Ehcache 2.x,JCache,Redis等。
Spring Cache对缓存的具体应用进行了集成。通过在业务方法上追加几个标记实现缓存的应用。
如何使用
1.开始使用前需要导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.然后在启动类注解@EnableCaching开启缓存
@SpringBootApplication
@EnableCaching //开启缓存
public class DemoApplication{
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3.缓存@Cacheable
@Cacheable注解会先查询是否已经有缓存,有会使用缓存,没有则会执行方法并缓存。
@Cacheable(value = "emp" ,key = "targetClass + methodName +#p0")
public List<NewJob> queryAll(User uid) {
return newJobDao.findAllByUid(uid);
}
此处的value是必需的,它指定了你的缓存存放在哪块命名空间。
此处的key是使用的spEL表达式,参考上章。这里有一个小坑,如果你把methodName换成method运行会报错,观察它们的返回类型,原因在于methodName是String而methoh是Method。
此处的User实体类一定要实现序列化public class User implements Serializable,否则会报java.io.NotSerializableException异常。
到这里,你已经可以运行程序检验缓存功能是否实现。
4.配置@CacheConfig
当我们需要缓存的地方越来越多,你可以使用@CacheConfig(cacheNames = {"myCache"})注解来统一指定value的值,这时可省略value,如果你在你的方法依旧写上了value,那么依然以方法的value值为准。
使用方法如下:
@CacheConfig(cacheNames = {"myCache"})
public class BotRelationServiceImpl implements BotRelationService {
@Override
@Cacheable(key = "targetClass + methodName +#p0")//此处没写value
public List<BotRelation> findAllLimit(int num) {
return botRelationRepository.findAllLimit(num);
}
.....
}
5.更新@CachePut
@CachePut注解的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用 。简单来说就是用户更新缓存数据。但需要注意的是该注解的value 和 key 必须与要更新的缓存相同,也就是与@Cacheable 相同。示例:
@CachePut(value = "emp", key = "targetClass + #p0")
public NewJob update(NewJob job) {
NewJob newJob = newJobDao.findAllById(job.getId());
newJob.update(job);
return job;
}
@Cacheable(value = "emp", key = "targetClass +#p0")//清空缓存
public NewJob save(NewJob job) {
newJobDao.save(job);
return job;
}
缓存使用问题
1.缓存优点
提升系统的查询效率。避免频繁访问DB,把DB数据加载到缓存,从缓存查询。
2.缓存和DB数据同步性
当对DB做增删改操作时,需要同时更新缓存,保持缓存和DB数据一致性。
3.当对DB进行更新时,对缓存是做更新还是做清除操作?
选择清除
4.先更新DB?还是先更新缓存?
//更新缓存(清除)
//更新DB
5.什么样的数据适合用缓存
- 共享共用数据(共享)
- 增删改频率小(增删改少)
- 频繁访问的数据(查询多)
- 对实时性要求高的数据(特殊需求)
缓存穿透、缓存雪崩、缓存击穿
缓存穿透:访问缓存没找到数据,查询DB数据,DB也没有
解决方案:将DB查询的空值也放入缓存,设置一个短的有效期
缓存雪崩:在某个时刻或时间段,缓存数据突然清空,导致大量请求访问DB数据
解决方案:针对不同类型数据设置不同缓存有效期,或随机指定有效期
缓存击穿:高并发访问某个一个缓存key,结果key突然失效,导致高并发访问DB数据
解决方案:设置永不过期;或者采用互斥锁将代码锁定
Redis持久化机制
redis相对于memcached缓存工具相比,存储类型丰富、支持持久化。
redis支持RDB和AOF两种持久化机制(将内存数据写入磁盘文件)。
RDB(快照模式)
可以在某一时刻将内存数据拍照,写入一个rdb文件中。特点:恢复快,但是会存在丢失问题。
save //备份命令,只要将rdb文件放到redis安装目录重新启动服务就会自动恢复。
//默认配置1、5、15分钟备份一次
save 900 1 //900秒发生1次key变化就自动save
save 300 10 //300秒发生10次key变化就自动save
save 60 10000 //60秒发生10000次key变化就自动save
AOF(日志模式)
可以将执行redis操作命令写入到一个aof文件中。特点:恢复慢,但是完整性好。默认关闭。
appendonly yes//yes开启aof持久化,no关闭
appendfilename "appendonly.aof" //aof文件名
# appendfsync always //一直记录,每个命令记录
appendfsync everysec //1秒记录一次
# appendfsync no //不记录
如果RDB和AOF同时启用,恢复时采用aof文件恢复。