java8高性能缓存_高性能本地缓存-caffeine

简介

1、Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件

2、支持异步加载,事件提交队列

3、内部使用W-TinyLFU算法,它的命中率非常高,内存占用更加的小

4、一般在redis之后,做二级缓存

优势

性能比较:

8个线程同时从缓存中读取

d85116f0440500a694ecf6c78f0459f8.png

8个线程同时从缓存中写入

6aed62c63335234896e4ae010a27addd.png

6个线程读取,2个线程写入

96b34242c50a9aa64f25f0825a582741.png

使用场景

1、二级缓存

原生使用方式

### 填充策略

1、手动加载// 初始化

public static void main(String[] args) {

Cache cache = Caffeine.newBuilder()

.expireAfterWrite(1, TimeUnit.SECONDS)

.expireAfterAccess(1, TimeUnit.SECONDS)

.maximumSize(10)

.build();

String key = "testKey";

//如果一个key不存在,那么会进入指定的函数生成value

Object value = cache.get(key, t -> setValue(key).apply(key));

cache.put("hello",value);

//判断是否存在如果不存返回null

Object ifPresent = cache.getIfPresent(key);

System.out.println(ifPresent);

//移除一个key

cache.invalidate(key);

}

public static Function setValue(String key){

return t -> key + "value";

}

2、同步加载构造Cache时候,build方法传入一个CacheLoader实现类。实现load方法,通过key加载value

public static void main(String[] args) {

String key = "key";

LoadingCache cache = Caffeine.newBuilder()

.maximumSize(100)

.expireAfterWrite(1, TimeUnit.MINUTES)

.build(k -> setValue(key).apply(key));

System.out.println(cache.get(key));

}

public static Function setValue(String key){

return t -> key + "value";

}

3、异步加载AsyncLoadingCache是继承自LoadingCache类的,异步加载使用Executor去调用方法并返回一个CompletableFuture。异步加载缓存使用了响应式编程模型

public static void main(String[] args) {

String key = "key";

AsyncLoadingCache cache = Caffeine.newBuilder()

.maximumSize(100)

.expireAfterWrite(1, TimeUnit.MINUTES)

.buildAsync(k -> setValue(key).get());

// 异步获取

CompletableFuture graph = cache.get(key);

graph.thenAccept(s -> {

System.out.println(s);

});

}

public static CompletableFuture setValue(String key){

return CompletableFuture.supplyAsync(() -> {

return key + "value";

});

}

springboot集成springboot-cache使用

1、添加jar依赖

org.springframework.boot

spring-boot-starter-cache

com.github.ben-manes.caffeine

caffeine

2、配置@EnableCaching注解@EnableCaching

@Configuration

public class LocalCacheConfig {

@Bean("caffeineCacheManager")

public CacheManager cacheManager(){

CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();

caffeineCacheManager.setCaffeine(Caffeine.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).initialCapacity(100).maximumSize(5000));

return caffeineCacheManager;

}

}

3、使用@Slf4j

@Service

@CacheConfig(cacheNames = "caffeineCacheManager")

public class SafetyInspectionTrackServiceImpl implements SafetyInspectionTrackService {

@Autowired

private SafetyInspectionTrackMapper safetyInspectionTrackMapper;

@Override

@Cacheable(key = "#id")

public SafetyInspectionTrackDO getById(Long id) {

log.info("进入缓存:{}",id);

return safetyInspectionTrackMapper.selectById(id);

}

@Override

@CacheEvict

public void clear(Long id){

log.info("清除缓存");

}

}

@Cacheable:配置在 getUsersByName方法上表示其返回值将被加入缓存。同时在查询时,会先从缓存中

获取,若不存在才再发起对数据库的访问

@CachePut:配置于方法上时,能够根据参数定义条件来进行缓存,其与 @Cacheable不同的是使用

@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都

会执行该方法并将执行结果以键值对的形式存入指定的缓存中,所以主要用于数据新增和修改

操作上

@CacheEvict:配置于方法上时,表示从缓存中移除相应数据

Caffeine常用配置说明

1、初始化参数initialCapacity: 初始的缓存空间大小

maximumSize: 缓存的最大条数

maximumWeight: 缓存的最大权重

expireAfterAccess: 最后一次写入或访问后经过固定时间过期

expireAfterWrite: 最后一次写入后经过固定时间过期

refreshAfterWrite: 创建缓存或者最近一次更新缓存后经过固定的时间间隔,刷新缓存

weakKeys: 打开key的弱引用

weakValues:打开value的弱引用

softValues:打开value的软引用

recordStats:开发统计功能

注意:

expireAfterWrite和expireAfterAccess同时存在时,以expireAfterWrite为准。

maximumSize和maximumWeight不可以同时使用

weakValues和softValues不可以同时使用

2、自动刷新refreshAfterWrite就是设置写入后多就会刷新,expireAfterWrite和refreshAfterWrite

的区别是,当缓存过期后,配置了expireAfterWrite,则调用时会阻塞,等待缓存计算完成,返

回新的值并进行缓存,refreshAfterWrite则是返回一个旧值,并异步计算新值并缓存

3、回收策略

#### (1)基于大小maximumSize 初始给定缓存大小,超过设置的值后,自动回收

#### (2)基于时间expireAfterAccess:在最后一次访问或者写入后开始计时

expireAfterWrite:在最后一次写入缓存后开始计时

expireAfte:自定义策略

#### (3)基于引用weakKeys:使用弱引用存储key

weakValues:使用弱引用存储value

softValues:使用软引用存储value

软引用: 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。

弱引用: 弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存

淘汰策略算法

1、FIFO:先进先出

在这种淘汰算法中,先进入缓存的会先被淘汰,会导致命中率很低。

2、LRU:最近最少使用算法

每次访问数据都会将其放在我们的队尾,如果需要淘汰数据,就只需要淘汰队首即可。仍然有个问题,如果有个数据在 1 分钟访问了 1000次,再后 1 分钟没有访问这个数据,但是有其他的数据访问,就导致了我们这个热点数据被淘汰。

3、LFU:最近最少频率使用

利用额外的空间记录每个数据的使用频率,然后选出频率最低进行淘汰。这样就避免了 LRU 不能处理时间段的问题。

4、W-tinyLFU算法

源码简析

e9f5afaad500390057b28b54b82bb737.png

1、在Caffeine中有个LocalCacheFactory类,他会根据你的配置进行具体Cache的创建。

910b81882065f5b5bfd98df8661c397a.png

2、在Caffeine中有个scheduleDrainBuffers方法,用来进行我们的过期任务的调度

ce44d6e0192611233f0e0765d5ae4db8.png

常见问题(Faq)

#### 1、固定数据(Pinning Entries)固定数据是不能通过驱逐策略去将数据删除的。当数据是一个有状态的资源时(如锁)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值