整合SpringCache简化缓存开发

引入依赖

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

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

写配置

spring:
  cache:
    type: redis # 缓存类型
    redis:
      time-to-live: 3600000 # 设置默认过期时间
      # key-prefix: CACHE_ # key前缀
      use-key-prefix: true # 是否启动前缀
      cache-null-values: true # 是否缓存空值

添加注解开启缓存 @EnableCaching

package com.hdb.pingmoweb.product;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableCaching
@EnableDiscoveryClient
@SpringBootApplication
public class PingmowebProductApplication {

    public static void main(String[] args) {
        SpringApplication.run(PingmowebProductApplication.class, args);
    }

}

修改默认配置

默认使用jdk进行序列化(可读性差),默认ttl为-1永不过期,自定义序列化方式需要编写配置类

配置修改缓存json

@Configuration
public class MyCacheConfig {
    @Bean
    public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {

        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
                .defaultCacheConfig();
        //指定缓存序列化方式为json
        config = config.serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        //设置配置文件中的各项配置,如过期时间
        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;
    }
}

需要缓存的return数据,在方法添加注解

 每一个需 要缓存的数据我们都来指定要放到那个名字的缓存。【缓存的分区(按照业务类型分)】

    @Cacheable(value = {"category"},key = "#root.method.name")//代表当前方法的结果需要缓存,如果缓存中有,方法不用调用。如果缓存中没有,会调用方法
    @Override
    public List<CategoryEntity> getLevel1Category() {
        QueryWrapper<CategoryEntity> query = new QueryWrapper<>();
        query.eq("parent_cid",0);
        long l = System.currentTimeMillis();
        List<CategoryEntity> categoryEntities = baseMapper.selectList(query);
        System.out.println("消耗时间:"+(System.currentTimeMillis()-l));
        return categoryEntities;
    }

缓存使用@Cacheable@CacheEvict

@CacheEvict 采用缓存失效模式

@CachePut 采用双写模式

第一个方法存放缓存,第二个方法清空缓存

// 调用该方法时会将结果缓存,缓存名为category,key为方法名
// sync表示该方法的缓存被读取时会加锁 // value等同于cacheNames // key如果是字符串"''"
@Cacheable(value = {"category"},key = "#root.methodName",sync = true)
public Map<String, List<Catalog2Vo>> getCatalogJsonDbWithSpringCache() {
    return getCategoriesDb();
}

//调用该方法会删除缓存category下的所有cache,如果要删除某个具体,用key="''"
@Override
@CacheEvict(value = {"category"},allEntries = true)
public void updateCascade(CategoryEntity category) {
    this.updateById(category);
    if (!StringUtils.isEmpty(category.getName())) {
        categoryBrandRelationService.updateCategory(category);
    }
}

清除多个key

    @RequestMapping({"/multiEvict"})
    @ResponseBody
    @Caching(evict = {
            @CacheEvict(value = "category",key = "'getLevel1Category'"),
            @CacheEvict(value = "category",key = "'getLevel1Category2'")
    })
    public String multiEvict(){
        return "multiEvict";
    }

Spring-cache的不足

读模式:

        缓存穿透:查询一个null数据。解决:缓存空数据;cache-null-values=true

        缓存击穿:大量并发进来同时查询一个正好过期的数据。解决:加本地锁;sync=true

        缓存雪崩:大量key同时过期。解决:加随机时间。加上过期时间 time-to-live: 3600000

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

        读写加锁

        引入Canal,感知到mysql的更新去更新数据库

        读多写多,直接去数据库查询

总结:常规数据(读多写少,即时性,一致性要求不高的数据)完全可以使用spring-cache

特殊数据:特殊涉及 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值