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;
}
查找了好多大佬的博客,最后自己整理了一下。