个人名片:
博主:酒徒ᝰ.
个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来。
本篇励志:三人行,必有我师焉。
本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》,SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
【SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 点击观看
、
二、JVM进程缓存
2. 初识Caffeine
缓存在日常开发中启动至关重要的作用,由于是存储在内存中,数据的读取速度是非常快的,能大量减少对数据库的访问,减少数据库的压力。我们把缓存分为两类:
- 分布式缓存,例如Redis:
- 优点:存储容量更大、可靠性更好、可以在集群间共享
- 缺点:访问缓存有网络开销
- 场景:缓存数据量较大、可靠性要求较高、需要在集群间共享
- 进程本地缓存,例如HashMap、GuavaCache:
- 优点:读取本地内存,没有网络开销,速度更快
- 缺点:存储容量有限、可靠性较低、无法共享
- 场景:性能要求较高,缓存数据量较小
我们今天会利用Caffeine框架来实现JVM进程缓存。
Caffeine是一个基于Java8开发的,提供了近乎最佳命中率的高性能的本地缓存库。目前Spring内部的缓存使用的就是Caffeine。GitHub地址:https://github.com/ben-manes/caffeine
学习:
- 缓存使用的基本API:
/**
* 基本查找
*/
@Test
void testBasicOps() {
//创建Cache对象
Cache<String, String> cache = Caffeine.newBuilder().build();
//存数据
cache.put("love", "刘亦菲");
//查数据
//可以查到数据
String love = cache.getIfPresent("love");
System.out.println("可以查到:" + love);
//查不到数据
//返回null
String wife = cache.getIfPresent("girl");
System.out.println("查不到,返回默认值: " + wife);
//不希望返回null,设置返回值
String girl = cache.get("girl", key -> {
return "wife";
});
System.out.println("查不到,返回设定值:" + girl);
}
Caffeine既然是缓存的一种,肯定需要有缓存的清除策略,不然的话内存总会有耗尽的时候。
- Caffeine的两种常用的缓存驱逐策略:
- 基于容量:设置缓存的数量上限
达到上限后清除缓冲也需要时间。
/**
* 设置缓冲数量上限
*/
@Test
void testEvictByNum() throws InterruptedException {
//设置缓冲数量上限为1个
Cache<String, String> cache = Caffeine.newBuilder()
.maximumSize(1)
.build();
cache.put("one", "迪迦");
cache.put("two", "赛罗");
cache.put("three", "银河");
//达到上限后需要时间清理,增加睡眠时间,留给程序清理缓冲
Thread.sleep(2000);
String one = cache.getIfPresent("one");
System.out.println(one);
String two = cache.getIfPresent("two");
System.out.println(two);
String three = cache.getIfPresent("three");
System.out.println(three);
}
- 基于时间:设置缓存的有效时间
/**
* 设置缓冲有效时间
* @throws InterruptedException
*/
@Test
void testEvictByTime() throws InterruptedException {
//设置缓冲有效时间为1秒
Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterWrite(Duration.ofSeconds(1))
.build();
// 或者
// Cache<String, String> cache = Caffeine.newBuilder()
// .expireAfterWrite(1, TimeUnit.SECONDS)
// .build();
cache.put("k", "修罗铠甲");
System.out.println(cache.getIfPresent("k"));
Thread.sleep(1020);
System.out.println(cache.getIfPresent("k"));
}
注意:在默认情况下,当一个缓存元素过期的时候,Caffeine不会自动立即将其清理和驱逐。而是在一次读或写操作后,或者在空闲时间完成对失效数据的驱逐。