Spring Cache的基本使用

文章目录

一、概述

常见的缓存的框架有RedisMemcachedGuavaCaffeine等等, 各有各的优势。如果我们的程序想要使用缓存,就要与这些框架耦合。聪明的架构师已经在利用接口来降低耦合了,利用面向对象的抽象和多态的特性,做到业务代码与具体的框架分离。但我们仍然需要显式地在代码中去调用与缓存有关的接口和方法,在合适的时候插入数据到缓存里,在合适的时候从缓存中读取数据。

Spring Cache利用了AOP,实现了基于注解的缓存功能,并且进行了合理的抽象,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解,就能实现缓存功能了。而且Spring Cache也提供了很多默认的配置,用户可以3秒钟就使用上一个很不错的缓存功能。

二、Spring Cache 的使用

2.1 环境搭建

① 引入Spring Cache坐标依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

② 配置:使用redis作为缓存

spring:
  cache:
    type: redis

③ 开启缓存功能注解:@EnableCaching

通常 Spring Cache 注解都可以用在类上或者方法级别上,如果用在类上,就是对该类的所有 public 方法生效

2.2 缓存的读模式 @Cacheable

@Cacheble注解一般用在查询方法上,表示这个方法有了缓存的功能,方法的返回值会被缓存下来。

  • 如果缓存中有,方法不用调用,如果缓存中没有,才会调用方法
  • key默认自动生成;缓存的名字:SimpleKey [](自主生成的key值)
  • 缓存的value的值。默认使用jdk序列化机制,将序列化后的数据存到redis
  • 默认ttl时间 -1;

测试:

@Cacheable({"category"})
public List<CategoryEntity> getLevel1Categorys() {
	......
}

我们发现缓存中的数据key就是自动生成的SimpleKey [],值是二进制数据。
在这里插入图片描述

2.3 自定义缓存配置

指定生成的缓存使用的key, key属性指定,接受一个SpEL

@Cacheable(value = {"category"},key = "#root.method.name")
public List<CategoryEntity> getLevel1Categorys() {
    return this.baseMapper.selectList(
            new QueryWrapper<CategoryEntity>().eq("parent_cid",0));
}

指定缓存的数据的存活时间: 配置文件中修改ttl

spring:
  cache:
    redis:
      time-to-live: 3600000

将数据保存为json格式, 自定义RedisCacheConfiguration即可:

@Configuration
@EnableCaching
public class MyCacheConfig {
    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
        RedisCacheConfiguration config  = RedisCacheConfiguration.defaultCacheConfig();
        //修改key和value的序列化机制
        config = config .serializeKeysWith(
                RedisSerializationContext.SerializationPair.fromSerializer(
                        new StringRedisSerializer()));
        config = config.serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(
                        new GenericJackson2JsonRedisSerializer()));

        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        //将配置文件中的所有配置都生效
        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixKeysWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }
        return config;
    }
}

此时缓存中的数据:
在这里插入图片描述
其他配置:

spring:
  cache:
    type: redis
    redis:
      # 缓存前缀,如果指定了前缀,就用指定的,如果没有,就使用缓存的名字作为前缀
      key-prefix: CACHE_
      use-key-prefix: true
      # 是否缓存null值,防止缓存穿透
      cache-null-values: true

2.4 @CachePut

加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用。它通常用在新增方法上。

2.5 @CacheEvict 删除缓存

缓存的写模式:失效模式

@CacheEvict(value = "category",key = "'getLevel1Categorys'")
public void updateCascade(CategoryEntity category) {
    ......
}

2.6 @Caching 多个操作

    @Caching(evict = {
            @CacheEvict(value = "category",key = "'getLevel1Categorys'"),
            @CacheEvict(value = "category",key = "'getCatelogJson'")
    })
    public void updateCascade(CategoryEntity category) {
		......
    }

三、Spring Cache 的不足

① 读模式

  • 缓存穿透:查询一个null数据,开启缓存空数据配置spring.cache.redis.cache-null-values=true
  • 缓存击穿:大量并发进来查询一个正好过期的数据,解决:加锁
  • 缓存雪崩:大量的key同时过期,解决:加过期时间,spring.cache.redis.time-to-live=3600000

② 写模式:缓存与数据库一致

  • 读写加锁
  • 引入Canal,感知到MySQL的更新去更新数据库
  • 读多写多,直接去数据库查询就行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值