spring-boot-starter-cache整合Redis并处理进程访问缓存的问题

引入

在以前的模板中,总是以RedisTemplate redisTemplate;形式注入到项目模块中。
但是做逻辑判断的时候,要人工的去写逻辑过程,比如①先去redis查②没有再去数据库查
③查到的数据放到缓存中。每次都要去写这样的逻辑显得代码实在是非常的拥挤和庞大
为了优化这一类的功能,spring框架引入了cache ,当和redis整合的时候,就让开发变得轻松,只关注业务。

构建

 		<dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-cacheartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>
        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-pool2artifactId>
            <version>2.6.0version>
       dependency>

yml

之前整合了redis配置,这里就直接配置cache

  redis:
    host: 192.168.182.128
    port: 6379
  cache:
    type: redis

主启动类@EnableCaching //开启缓存,或者config类上加@EnableCaching,让主启动类扫描到就可以了

使用
在你需要做缓存处理的方法上加注解:@Cacheable("<你的key>"),这样你就不用写RedisTemplate 方法了

默认行为

  1. 缓存存在,则方法不调用
  2. key默认自动生成,缓存名字::SimpleKey []
  3. 过期时间 ttl = -1
  4. 缓存的值,默认生成java序列化,序列化后存入到redis

自定义行为

  1. 指定生成缓存使用的key
  2. 指定缓存数据的存活时间 ymltime-to-live: 3600000看你需求
  3. 将数据保存为json格式,方便其他接口兼容 自定义RedisCacheConfiguration

配置类

@Configuration
@EnableCaching
@EnableConfigurationProperties(CacheProperties.class)
public class RedisCacheConf {
    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

//引入自定义的yml的cache配置
        CacheProperties.Redis propertiesRedis = cacheProperties.getRedis();
        if(propertiesRedis.getTimeToLive()!=null){
            config = config.entryTtl(propertiesRedis.getTimeToLive());
        }
        if(propertiesRedis.getKeyPrefix()!=null){
            config = config.prefixKeysWith(propertiesRedis.getKeyPrefix());
        }
        if(propertiesRedis.isCacheNullValues()){
            config = config.disableCachingNullValues();
        }
        if(propertiesRedis.isUseKeyPrefix()){
            config = config.disableKeyPrefix();
        }
        return config;

    }
}

可能有些项目这个配置类,会出现某些问题,可以替换下面的配置类,2个配置你自己选一个

配置类

@EnableCaching //开启缓存
@Configuration  //配置类
@EnableConfigurationProperties(CacheProperties.class)
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory,CacheProperties cacheProperties) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        //获取自定义yml
        CacheProperties.Redis propertiesRedis = cacheProperties.getRedis();
        if(propertiesRedis.getTimeToLive()!=null){
            config = config.entryTtl(propertiesRedis.getTimeToLive());
        }
        config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
        if(propertiesRedis.isCacheNullValues()){
            config = config.disableCachingNullValues();
        }
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();

        return cacheManager;
    }
}

============================================================================================================================================================
spring-Cache的不足问题:

读模式:

  1. 缓存穿透:查询一个null值。解决:缓存空数据:配置ymlcache-null-values: true
  2. 缓存击穿:大量并发进来同时查询一个正好过期的数据。解决:加锁,默认是无加锁,可以@Cacheable(value = "",sync = true)
  3. 缓存雪崩:大量key同时过期,解决加随机时间,ymltime-to-live: 3600000 #1小时

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

1.读写加锁
2. 引入Canal,感知到MySql的更新去更新数据库
3. 读多写多,直接去数据库查就可以了

常规数据,完全可以用使用spring-cache
特殊数据,另外设计

你可能感兴趣的:(springboot,缓存,redis,spring)