springboot整合Caffeine缓存返回旧值同时刷新新值

springboot整合Caffeine缓存返回旧值同时刷新新值

主要就是需求请求来的时候不能等待缓存刷新,先返回旧的缓存值,新的数据查询完成后,刷新缓存返回新的缓存。

依赖:

  <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.7.0</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
     <!-- redis 相关 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

@EnableCaching 加在启动函数上开启缓存

@SpringBootApplication
@EnableCaching
public class  APIApplication {

    public static void main(String[] args) {

        SpringApplication.run(APIApplication.class);

    }
}

service接口

@Override
    @Cacheable(value = "Test",key = "#test")//目标方法参数是id,key可以直接写id,key就是缓存中的主键
    public String test(String test) {

        try{
            return test();
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
            return "";
    }

    @Override
    public String test() throws InterruptedException {
        logger.info("进入testapi");

        JedisShardInfo jedisShardInfo1 = new JedisShardInfo("127.0.0.1", 6379);
        jedisShardInfo1.setPassword("123456");
        // 1. 设置IP地址和端口
        Jedis resource = jedisShardInfo1.createResource();
        // 3. 获取数据
        String value = resource.get("111");

        // 4.释放资源
        resource.close();

    // 睡一会为了验证是否立即返回
        Thread.sleep(15000);
        System.out.println(value);
        return value;
    }

CacheConfig配置缓存

/**
 * @program: machineAPI
 * @description:
 * @author: Mr.YHZ
 * @create: 2020-08-14 15:58
 **/
@Configuration
public class CacheConfig {

//日志配置,不需要就将此句删除 下面的logger换成System.out.println();
    private static final Logger logger =  LoggerFactory.getLogger(CacheConfig.class);

//    线程的缓存异步加载
    private ExecutorService executorService = Executors.newFixedThreadPool(5);
    @Autowired
    CacheLoader cacheLoader;

    @Autowired
    CacheConfig CacheConfig;

    @Autowired
    private ApiService apiService;

    @Value("60")
    private Integer duration;


    /**
     *
     * 指定 refreshAfterWrite该参数时 必须重写 cacheLoader
     * 相当于在构建LoadingCache对象的时候 build()方法中指定过期之后的加载策略方法
     *
     * @return
     */
    @Bean
    public CacheLoader<String, Object> cacheLoader() {
        CacheLoader<String, Object> cacheLoader = new CacheLoader<String, Object>() {
            @Override
            public Object load(String key) throws Exception {
               logger.info("缓存加载中......key:{}",key);
                return null;
            }

//
//            public Future<Object> asyncReload(String key, String oldValue, Executor executor) throws Exception {
//                logger.info("......后台线程池异步刷新:" + key);
//                ListenableFutureTask<Object> futureTaskTest = ListenableFutureTask.create(()->{
//                    String test = apiService.test("test");
//                    logger.info("缓存重载中......newValue:{}",test);
//                    return test;
//                });
//                return (ListenableFuture<Object>) executorService.submit(futureTaskTest);
//            }
            // 重写这个方法将oldValue值返回回去,进而刷新缓存
            @Override
            public Object reload(String key, Object oldValue) throws Exception {
                logger.info("缓存重载中......key:{}",key);
//先返回了旧值异步调用service获取缓存手动方式进行了缓存的刷新
                ListenableFutureTask<Object> futureTaskTest = ListenableFutureTask.create(()->{
                    String test = apiService.test();
                    Cache testCache = CacheConfig.cacheManagerWithCaffeine().getCache("Test");
                    testCache.put("test",test);
                    logger.info("缓存重载中......newValue:{}",test);
                    return test;
                });
                logger.info("缓存重载中......oldValue:{}",oldValue);
                executorService.submit(futureTaskTest);
                return oldValue;
            }
        };
        return cacheLoader;
    }

    //配置CacheManager
    @Bean(name = "caffeine")
    public CacheManager cacheManagerWithCaffeine() {

        CaffeineCacheManager cacheManager = new CaffeineCacheManager();

        Caffeine caffeine = Caffeine.newBuilder()
                //cache的初始容量值
//                .initialCapacity(100)
                //maximumSize用来控制cache的最大缓存数量,maximumSize和maximumWeight(最大权重)不可以同时使用,
//                .maximumSize(1000)
                //最后一次写入或者访问后过久过期
//                .expireAfterAccess(duration, TimeUnit.SECONDS)
                //创建或更新之后多久刷新,需要设置cacheLoader
                .refreshAfterWrite(duration, TimeUnit.SECONDS)
                ;
        cacheManager.setCaffeine(caffeine);
        cacheManager.setCacheLoader(cacheLoader);

        //缓存名称
        Collection<String> names=new ArrayList<>();
        names.add("Test");
        cacheManager.setCacheNames(names);//根据名字可以创建多个cache,但是多个cache使用相同的策略
        cacheManager.setAllowNullValues(false);//是否允许值为空

        return cacheManager;
    }

查找了好多大佬的博客,最后自己整理了一下。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值