SpringBoot 2.x redis + Spring Cache 缓存管理

SpringBoot 2.x redis+cache 作缓存

背景

通常在使用Redis 直接做业务缓存时,判断逻辑流程如下:
SpringBoot 2.x redis + Spring Cache 缓存管理_第1张图片
代码逻辑如下:

  public List<String> getRedisCacheResult(){
        //查询缓存结果集 
        Object test = redisTemplate.opsForValue().get("test");
        //缓存为空 
        if(ObjectUtils.isEmpty(test)){
            //和DB 交互,获取业务数据
            List<String> list = new ArrayList<>();
            list.add("test");
            
            //将DB 查询的结果集放入缓存
            redisTemplate.opsForValue().set("test",list);
            return list;
        }
        //缓存存在结果集,返回缓存中的结果集
        return (List<String>)test;
        
    }

整个代码逻辑流程会发现,每次进行数据缓存的时候,都会存在代码冗余逻辑判断。该逻辑判断如果采用Spring Cache + Redis 注解的方式,代码更加简洁方便

依赖

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

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

配置

@EnableCaching 注解用来开启缓存,并配置Redis缓存管理器。如果未配置该注解,则配置的cache +redis无法生效

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
  @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory){
        //设置key 默认过期时间未30min
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(30L)).disableCachingNullValues();
        return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory))
                .cacheDefaults(redisCacheConfiguration).transactionAware().build();
    }

}

Spring cache 使用

package com.corn.redis.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * author:zj
 * Date:2020/4/5
 * Time:15:18
 */
@Service
@CacheConfig(cacheNames = "RedisCacheService")
@Slf4j
public class RedisCacheService {

    /**
     * 将结果集缓存,当结果集已缓存,从缓存中获取结果集,一般长用于数据删除
     * @return
     */
    @Cacheable(value = "cacheTest",key = "#root.methodName")
    public List<String> getRedisCache(){
        List<String> list = new ArrayList<>();
        list.add("test");
        return list;
    }

    /**
     * 将结果集缓存,和@Cacheable 的区别是,该缓存不管缓存是否存在,每次都会更新缓存
     * 常用于更新结果集
     * @return
     */
    @CachePut(value = "cacheTest",key = "#root.methodName")
    public List<String> updateRedisCache(){
        List<String> list = new ArrayList<>();
        list.add("test");
        return list;
    }

    /**
     * 根据key 删除指定存储空间下的缓存
     *
     */
    @CacheEvict(value = "cacheTest",key = "#root.methodName")
    public void deleteRedisCache(){
        log.info("清理指定key下缓存");
    }

    /**
     * 清空当前缓存空间下的所有缓存
     */
    @CacheEvict(allEntries = true)
    public void deleteAllCache(){
        log.info("清除当前缓存空间下的所有缓存");
    }

}

Spring Cache 注解详解

常用注解

注解 作用 使用场景
@CacheConfig 类级别注解,常用于设置类缓存共通的配置,比如@CacheConfig(cacheNames = “RedisCacheService”) 设置该类下缓存的缓存空间为RedisCacheService 常用于统一整个类下的缓存空间及key生成策略
@Cacheable 将方法的查询结果缓存起来,如果缓存中有值,则不在执行该方法 常用于查询数据业务逻辑
@CachePut 将结果集缓存,和@Cacheable 的区别是,该缓存不管缓存是否存在,每次都会更新缓存常用于更新结果集 常用于数据结果集更新时使用
@CacheEvict 根据键值进行删除缓存 常用于数据清除数据时同时 将缓存进行清除

注解参数详解

@Cacheable

  1. key 缓存的键值,默认不指定的情况下,采用SimpleKeyGenerator 作为key的生成策略;
    key 结合使用Spring EL :
Example Description
#root.methodName 被调用的方法名称作为key
#root.method.name 被调用的方法作为key
#root.target 被调用的方法对象作为key
#root.targetClass 当前方法所在类作为key
#root.args[0] 当前方法中的参数作为key

key 自定义方式使用:

@Cacheable(cacheNames="user", key="#isbn")
public User findUser(User isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable(cacheNames="user", key="#isbn.rawNumber")
public User findUser(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable(cacheNames="user", key="T(someType).hash(#isbn)")
public User findUser(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
  1. keyGenerator 自定义key 值生成策略
  2. cacheManager 指定当前的key 所在的缓存处理器,
  3. value 指定当前缓存所在的缓存空间
  4. sync 是否同步缓存,使用场景:
    在多线程环境中,可能会出现相同的参数的请求并发调用方法的操作,默认情况下,spring cache 不会锁定任何东西,相同的值可能会被计算几次,这就违背了缓存的目的
    对于这些特殊情况,可以使用sync属性。此时只有一个线程在处于计算,而其他线程则被阻塞,直到在缓存中更新条目为止。
@Cacheable(cacheNames="user", sync=true) 
public User test(String id) {...}
  1. condition 满足condition 的条件时,进行结果缓存
//当name 的长度小于16 时进行数据的缓存,否则不进行缓存
@Cacheable(cacheNames="user", condition="#name.length() < 16") 
public User findUser(String name)
  1. unless 满足unless 条件时不缓存
//当name 长度小于32 且 查询到的用户年龄大于12 岁时才进行结果集的缓存
@Cacheable(cacheNames="user", condition="#name.length() < 32", unless="#result.age<12")
public User findUser(String name)

总结

Spring cache + redis 进行缓存管理的方式,在一定程度上,减少了代码。实际使用过程中还是需要结合业务场景,决定是单独使用Redis 还是使用Redis + Spring Cache 组合方式

参考:
https://www.jianshu.com/p/931484bb3fdc

你可能感兴趣的:(redis)