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

简介

1、Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件 2、支持异步加载,事件提交队列 3、内部使用W-TinyLFU算法,它的命中率非常高,内存占用更加的小 4、一般在redis之后,做二级缓存

优势

性能比较: 8个线程同时从缓存中读取

image-5d2b3946363c4a42b37670daea3e9e6e.png 8个线程同时从缓存中写入

image-d0f1c189b6924335b1b918a55d7a08e6.png 6个线程读取,2个线程写入

image-6705a4761b7d430cbe984639e3d677d3.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算法

源码简析

fc6a3faccb57b13f27fc449851bf3a0c.png

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

image-4749327b8f074bf4a96cc7d3db92c95f.png

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

image-ecf5a2c086e34fc1b0eeff52accc6930.png

常见问题(Faq)

1、固定数据(Pinning Entries)

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值