微信图片_20220114184632.png

1.Caffeine框架来实现JVM进程缓存。

Caffeine是一个基于Java8开发的,提供了近乎最佳命中率的高性能的本地缓存库。目前Spring内部的缓存使用的就是Caffeine。Caffeine的性能非常好,GitHub地址:https://github.com/ben-manes/caffeine

1).缓存使用的基本API:

  1. @Test
  2. void testBasicOps() {
  3. // 构建cache对象
  4. Cache<String, String> cache = Caffeine.newBuilder().build();
  5. // 存数据
  6. cache.put("gf", "迪丽热巴");
  7. // 取数据
  8. String gf = cache.getIfPresent("gf");
  9. System.out.println("gf = " + gf);
  10. // 取数据,包含两个参数:
  11. // 参数一:缓存的key
  12. // 参数二:Lambda表达式,表达式参数就是缓存的key,方法体是查询数据库的逻辑
  13. // 优先根据key查询JVM缓存,如果未命中,则执行参数二的Lambda表达式
  14. //defaultGF这个key不存在,所以查询数据库(模拟查询),结果返回“柳岩”
  15. String defaultGF = cache.get("defaultGF", key -> {
  16. // 根据key去数据库查询数据
  17. return "柳岩";
  18. });
  19. System.out.println("defaultGF = " + defaultGF);
  20. }

上述代码运行结果如下:
image.png

2.缓存的清除策略

Caffeine既然是缓存的一种,肯定需要有缓存的清除策略,不然的话内存总会有耗尽的时候。
Caffeine提供了三种缓存驱逐策略:

  • 基于容量:设置缓存的数量上限// 创建缓存对象 ```java // 创建缓存对象 Cache cache = Caffeine.newBuilder() //检测时设置睡眠时间效果更好,如果执行完将直接退出,没有机会清除无用的数据 .maximumSize(1) // 设置缓存大小上限为 1 .build();

/ 基于大小设置驱逐策略: / @Test void testEvictByNum() throws InterruptedException { // 创建缓存对象 Cache cache = Caffeine.newBuilder() // 设置缓存大小上限为 1 .maximumSize(1) .build(); // 存数据 cache.put(“gf1”, “柳岩”); cache.put(“gf2”, “范冰冰”); cache.put(“gf3”, “迪丽热巴”); // 延迟10ms,给清理线程一点时间 Thread.sleep(10L); // 获取数据 System.out.println(“gf1: “ + cache.getIfPresent(“gf1”)); System.out.println(“gf2: “ + cache.getIfPresent(“gf2”)); System.out.println(“gf3: “ + cache.getIfPresent(“gf3”)); }

  1. 缓存大小上线为1,清理缓存<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/25449971/1642163081440-6629d3b8-fe99-4594-9402-a5c8693fee3d.png#clientId=uccf1afbe-cc7e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=136&id=u171e2e76&margin=%5Bobject%20Object%5D&name=image.png&originHeight=271&originWidth=728&originalType=binary&ratio=1&rotation=0&showTitle=false&size=22104&status=done&style=none&taskId=ude19940d-5622-48ed-bf8e-f3c47c8a4a4&title=&width=364)
  2. - **基于时间**:设置缓存的有效时间// 创建缓存对象
  3. ```java
  4. Cache<String, String> cache = Caffeine.newBuilder()
  5. // 设置缓存有效期为 10 秒,从最后一次写入开始计时
  6. .expireAfterWrite(Duration.ofSeconds(10))
  7. .build();
  8. /*
  9. 基于时间设置驱逐策略:
  10. */
  11. @Test
  12. void testEvictByTime() throws InterruptedException {
  13. // 创建缓存对象
  14. Cache<String, String> cache = Caffeine.newBuilder()
  15. .expireAfterWrite(Duration.ofSeconds(1)) // 设置缓存有效期为 10 秒
  16. .build();
  17. // 存数据
  18. cache.put("gf", "柳岩");
  19. // 获取数据
  20. System.out.println("gf: " + cache.getIfPresent("gf"));
  21. // 休眠一会儿
  22. Thread.sleep(1200L);
  23. System.out.println("gf: " + cache.getIfPresent("gf"));
  24. }

运行结果如下:
image.png

  • 基于引用:设置缓存为软引用或弱引用,利用GC来回收缓存数据。性能较差,不建议使用。

注意:在默认情况下,当一个缓存元素过期的时候,Caffeine不会自动立即将其清理和驱逐。而是在一次读或写操作后,或者在空闲时间完成对失效数据的驱逐。