当前位置: 首页>后端>正文

SpringCache与缓存问题

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文件恢复。


https://www.xamrdz.com/backend/33x1938682.html

相关文章: