package com.study.caffeine_cache;
import com.alibaba.fastjson.JSON;
import com.github.benmanes.caffeine.cache.*;
import com.study.domin.Airport;
import com.study.mapper.AirPortMapper;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* @author shengda.ji
* @date 2019/9/23 11:56 AM
*/
@RestController
@RequestMapping("/")
public class Controller {
@Autowired
private AirPortMapper mapper;
StopWatch stopWatch = new StopWatch("任务耗时");
@GetMapping(value = "/get_all_airport")
public List<Airport> testCustomInterface() {
stopWatch.start("获取所有机场信息");
List<Airport> result = mapper.getAll();
stopWatch.stop();
System.err.println(stopWatch.prettyPrint());
return result;
}
Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.expireAfterAccess(1, TimeUnit.MINUTES)
.maximumSize(10000)
.build();
@GetMapping(value = "/get_all_airport_cache")
public List<Airport> testCustomInterface_Cache() {
stopWatch.start("获取所有机场信息_cache");
String key = "all_airport";
// 根据key查询一个缓存,如果没有返回NULL
String graph = cache.getIfPresent(key);
if (StringUtils.isEmpty(graph)) {
List<Airport> result = mapper.getAll();
cache.put(key, JSON.toJSONString(result));
System.out.println("————————————————————————————————————————————————没有缓存————————————————————————————————————————————————");
stopWatch.stop();
System.err.println(stopWatch.prettyPrint());
return result;
} else {
System.out.println("——————————————————————————————————————————————————有缓存————————————————————————————————————————————————");
stopWatch.stop();
System.err.println(stopWatch.prettyPrint());
return JSON.parseArray(graph, Airport.class);
}
}
LoadingCache<String, List<Airport>> loadingCache = Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(10, TimeUnit.SECONDS)
.refreshAfterWrite(1, TimeUnit.SECONDS)
.build(new CacheLoader<String, List<Airport>>() {
@Nullable
@Override
public List<Airport> load(@NonNull String i) {
System.out.println("缓存里没有,load数据");
return mapper.getAll();
}
@Override
public List<Airport> reload(@NonNull String key, @NonNull List<Airport> oldValue) {
System.out.println("缓存里没有,reload数据" + oldValue.size());
return mapper.getAll();
}
});
@GetMapping(value = "/get_all_airport_loading_cache")
public List<Airport> testCustomInterfaceLoadingCache() {
stopWatch.start("获取所有机场信息_loading_cache");
String key = "all_airport";
List<Airport> result = loadingCache.get(key);
stopWatch.stop();
System.err.println(stopWatch.prettyPrint());
return result;
}
/**
* 和cache一样,只不过返回的CompletableFuture
*/
AsyncLoadingCache<String, List<Airport>> asyncCache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.expireAfterAccess(1, TimeUnit.MINUTES)
.refreshAfterWrite(1, TimeUnit.MINUTES)
.maximumSize(10000)
.buildAsync(new CacheLoader<String, List<Airport>>() {
@Nullable
@Override
public List<Airport> load(@NonNull String i) throws Exception {
System.out.println("缓存里没有,load数据");
return mapper.getAll();
}
@Override
public List<Airport> reload(@NonNull String key, @NonNull List<Airport> oldValue) {
System.out.println("缓存里没有,reload数据");
return mapper.getAll();
}
@Override
public Map<String, List<Airport>> loadAll(Iterable<? extends String> keys) {
Map<String, List<Airport>> map = new HashMap<>();
for (String i : keys) {
map.put(i + "1", new ArrayList<>());
}
return map;
}
});
@GetMapping(value = "/get_all_airport_async_cache")
public List<Airport> testCustomInterfaceAsyncCache() throws ExecutionException, InterruptedException {
stopWatch.start("获取所有机场信息_async_cache");
String key = "all_airport";
CompletableFuture<List<Airport>> completableFuture = asyncCache.get(key);
List<Airport> result = completableFuture.get();
stopWatch.stop();
System.err.println(stopWatch.prettyPrint());
return result;
}
}
看下结果:
我的数据量是2000+条
分别说:
- 174ms:无缓存,第一次从数据库取数据。
- 57ms:使用cache。但是没添加缓存,准确来说也是查询数据库,但是因为mysql本身的优化,返回上次查询结果,所以较第一次少很多。
- 2ms:明显使用到缓存 cache。
- 30ms:和57ms同理,loading_cache内无数据,查询数据库,30ms。
- 9ms和0ms:使用到loading_cache缓存。
- 24ms:和57ms同理,async_cache内无数据,查询数据库,24ms。
- 0ms:使用到async_cache缓存。