本地进程缓存
缓存在日常开发中起到至关重要的作用,由于是存储在内存中,所以数据的读取速度非常快,能大量的减少对数据库的访问,减少数据库的压力。我们把缓存分为两类:
* | 分布式缓存(例如Redis) | 进程本地缓存(例如Hashmap,Caffeine) |
---|---|---|
优点 | 存储容量更大,可靠性更好,可以在集群间共享 | 读取本地内存,没有网络开销,速度更快 |
缺点 | 访问缓存有网络开销 | 存储容量有限,可靠性较低(服务重启缓存就没了),无法共享(多个服务直接无法互相访问) |
场景 | 缓存数据量较大,可靠性要求较高,需要在集群间共享 | 性能要求较高,缓存数据量较小 |
Caffeine
GitHub官方文档: https://github.com/ben-manes/caffeine/wiki/Home-zh-CN
Caffeine是基于Java8开发的,提供了近乎最佳命中率的高性能的本地缓存库。目前Spring内部使用的就是Caffeine。
Caffeine提供了三种缓存驱逐策略:
1. 基于容量,设置缓存最大上线
/**
* 基于容量,设置缓存最大上线
*/
@Test
void test02() throws InterruptedException {
Cache<String,String> caffeine = Caffeine.newBuilder()
.maximumSize(2) //设置最大上线为2
.build();
caffeine.put("name","张三");
caffeine.put("age","44");
caffeine.put("day","3.3");
Thread.sleep(10); //给清理线程一点时间来清除
System.out.println("name:" + caffeine.getIfPresent("name")
+ ",age:" + caffeine.getIfPresent("age")
+ ",day:"+caffeine.getIfPresent("day")
);
}
--- 控制台打印如下
name:null,age:44,day:3.3
2. 基于时间,设置缓存有效期
/**
* 基于时间,设置缓存有效期
*/
@Test
void test03() throws InterruptedException {
Cache<Object, Object> caffeine = Caffeine.newBuilder()
.expireAfterWrite(Duration.ofSeconds(1)) //设置缓存有效期为10s,从最后一次写入有效期开始计时
.build();
caffeine.put("name","张三");
System.out.println("name:" + caffeine.getIfPresent("name"));
caffeine.put("age","44");
caffeine.put("day","3.3");
Thread.sleep(1000);
System.out.println("name:" + caffeine.getIfPresent("name")
+ ",age:" + caffeine.getIfPresent("age")
+ ",day:"+caffeine.getIfPresent("day")
);
}
--- 控制台打印如下
name:张三
name:null,age:null,day:null
3. 基于引用
设置缓存为软引用或弱引用,利用GC来回收缓存数据。性能较差,不建议使用。
默认情况下,当一个缓存元素过期的时候,Caffeine不会立即清理和驱逐。而是在一次读或写操作后,或者在空闲时间完成对失效数据的驱逐。