栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

集成缓存 -- Spring Cache

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

集成缓存 -- Spring Cache

Spring Cache
      • 前言
        • 源码
        • 入门
        • springBoot 自动配置缓冲中间件。
        • 介绍几个注解
      • 整合SpringCache
        • 引入依赖
        • 开启缓存
        • 配置属性
        • 了解注解
        • 录入测试文本
      • 测试案例分析
        • 可能遇到的问题,击穿 雪崩 穿透
        • 解决雪崩
        • 解决穿透
      • 自定义缓存
      • 总结

前言

对于一些后端系统,如果不是电商系统,在前文中的redis集成之后,一般会采用使用redis 封装工具类进行存储一些数据,但是在springBoot前 spring已经集成了缓存中间件,一般来说普通的缓存可以使用缓存中间件进行使用,比如说配置列表,比如说一些固定的json,库存配置,地址配置,状态机配置,对于一般不怎么改动的且并发量在100以内的使用注解配置要舒服的多,今天还是看了一下源码顺便把这个好用的缓存件总结下来。

spring 从3.1就开始定义了Cache 和CaheManager 接口来实现工程上面的缓存技术并支持JCache注解来简化开发,具体内容可以参考spring的官网文档。Cache接口为缓存组件规范了定义,包含缓存的各种操作集合;

源码 入门

关于缓存管理器接口,提供了 获取缓存,和通过名字获取缓存

缓存件里面提供了多种缓存中间件,有普通的也有组件化以及redis等缓存管理器

通过当前map来管理不同名字的缓存

在赋予缓存名字的时候会根据是否存在命名,如果没有会创建当前map缓存方法

由上文源码可以了解到

缓存 — 缓存管理器 – 缓存

springBoot 自动配置缓冲中间件。


通过注入缓存的搜索器去搜索各种缓存配置

通过mapping来映射缓存类型配置

缓存类型配置由map集合收纳

缓存类型枚举

文中以redis为例 通过映射redis类型获取 redis 缓存配置 通过源码可以看到构造函数 存在redisCacheConfiguration如果不存在默认配置,通过bean帮我们创建好了 CacheManager 管理器

从CacheProperties Application写入的Spring.Cache里面注入过来的缓存名称。

Spring.Cache 配置

如果没有缓存名字会自己初始化一个缓存名称


拿到管理器之后确定配置 获取管理器配置

下面关于如果没有redisCacheConfigration那么默认创建可以看到key 是String 序列号,值是JDK序列号,如果后期脚本使用那么存储在redis缓存的值需要进行再处理为json

从文中可以看到,缓存管理器以及缓存只要开启缓存,并配置简单的缓存类型,那么缓存中间件就可以自动化为我们配置好所需要的所有管理器,以及缓存

SpringBoot已经启用自动化配置进行缓存封装,这种情况,以常用的redis 为例进行缓冲示例

介绍几个注解
  • @Cacheable 触发保存到缓存 常用
  • @CacheEvict 触发将缓冲删除
  • @CachePut 不影响方法执行更新
  • @Cacheing 组合多个操作
  • @CacheConfig 在类级别共享缓冲配置
整合SpringCache 引入依赖
     
            org.springframework.boot
            spring-boot-starter-cache
        
        
        
            org.springframework.boot
            spring-boot-starter-redis
            1.3.2.RELEASE
        

开启缓存

配置属性
spring.cache.type=redis

spring.cache.redis.time-to-live=6000
# 防止穿透
spring.cache.redis.cache-null-values=true
# 指定前缀 就用指定的前缀,如果没有默认使用缓存名字作为前缀
spring.cache.redis.key-prefix=cache_
spring.cache.redis.use-key-prefix=true

了解注解

录入测试文本

测试案例分析

@Cacheable 代表当前结果需要缓存 如果缓存中有 方法不需要调用 ,如果缓存没有查询结果映射到redis缓存中去

	@AliasFor("cacheNames")
	String[] value() default {};
可能遇到的问题,击穿 雪崩 穿透

每个需要缓存的数据 指定业务类型 放到缓存分区管理器中,方便后期从redis 获取

缓存分区 CacheNames 缓存建 key = "#root.methodName"方法名
配置文件 -> spring.cache.redis.key-prefix=cache_ 缓存前缀 cache_

解决雪崩

spring.cache.redis.time-to-live=6000 过期时间 雪崩设置过期时间 6000 毫秒

解决穿透

spring.cache.redis.cache-null-values=true 穿透是否存储null 解决

击穿 设置 注解 sync = true 过期同步线程获取
@Cacheable(value = {"location"},key = "#root.methodName",sync = true)

自定义缓存

前面源码说到, 由于存储值进行的默认是JDK序列, 如果没有RedisCacheConfiguration 才会创建

捋一下思路

 CacheAutoConfiguration ->  getConfigurationClass -> RedisCacheConfiguration ->cacheManager ->   RedisCacheManager ->determineConfiguration ->  判断是否为空->

由于缓存的redis 过期时间为空 且 序列化方式为JDK 序列存储,所以建议定义存储 为 json 方便后面使用

源码构造配置

 //  判断是否为空 ->
 
 config.serializevaluesWith(SerializationPair
				.fromSerializer(new JdkSerializationRedisSerializer(classLoader)));

	RedisCacheConfiguration(CacheProperties cacheProperties,
			CacheManagerCustomizers customizerInvoker,
			ObjectProvider redisCacheConfiguration) {
		this.cacheProperties = cacheProperties;
		this.customizerInvoker = customizerInvoker;
		this.redisCacheConfiguration = redisCacheConfiguration.getIfAvailable();
	}

改造

@EnableConfigurationProperties(CacheProperties.class)
@Configuration
public class MyCacheConfig {

    
    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        config = config.serializevaluesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        config.serializeKeysWith( RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        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;
    }
}

总结

读多写少 及时性 一致性要求不高的数据, 完全可以使用Srping - Cache 特殊情况需要强及时性及数据一致性,可以进行特殊设计

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/644721.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号