本地高性能缓存Caffeine

Caffeine是一个基于Java 8的高性能本地缓存框架,使用W-TinyLFU算法,实现了高命中率和低内存消耗。它提供了多种缓存类型和驱逐策略,包括手动和自动加载、基于大小、时间和引用的驱逐。Caffeine还支持统计功能和动态调整的窗口大小,以优化缓存性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Caffeine介绍

        Caffeine是一个基于Java 8的高性能本地缓存框架,采用了W-TinyLFU(LUR和LFU的优点结合)算法,实现了缓存高命中率、内存低消耗。缓存性能接近理论最优,属于是Guava Cache的增强版。在并发读、并发写、并发读写三个场景下Caffeine的性能最优。

二、使用方式

1、在pom.xml 中添加 caffeine 依赖

<dependency>    
    <groupId>com.github.ben-manes.caffeine</groupId>      
    <artifactId>caffeine</artifactId>  
</dependency>

2、参数说明

参数

说明

expireAfterWrite

写缓存后n秒钟过期

expireAfterAccess

读写缓存后n秒钟过期

refreshAfterWrite

写入后多久刷新,刷新是基于访问(支持异步和同步刷新)。

只阻塞当前数据加载的线程,其他线程返回旧值,刷新完成才会返回新的取值。

expireAfter

自定义淘汰策略, Caffeine 通过时间轮算法来实现不同key 的不同过期时间

maximumSize

缓存key最大个数

weakKeys

key设置为弱引用,在 GC 时可以直接淘汰

weakValues

value设置为弱引用,在 GC 时可以直接淘汰

softValues

value设置为软引用,在内存溢出前可以直接淘汰

executor

选择自定义线程池,默认线程池是 ForkJoinPool.commonPool()

maximumWeight

设置缓存最大权重

weigher

设置具体key权重

recordStats

缓存的统计数据,比如命中率等

removalListener

缓存淘汰监听器

writer

缓存写入、更新、淘汰的监听器

3、创建对象

private LoadingCache<String, List<Integer>> cache = Caffeine.newBuilder()
        //cache最大缓存数
        .maximumSize(500)
        //设置写缓存后n秒钟过期
        .expireAfterWrite(17, TimeUnit.SECONDS)
        .build();

4、缓存类型

4.1 手动加载cache:提供搜索查找、更新和移除缓存元素。缓存数据不存在,需要手动加载。

Cache<String, List<Integer>> cache = Caffeine.newBuilder()
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .maximumSize(500)
        .build(new CacheLoader<String, List<Integer>>() {
            @Override
            public List<Integer> load(String key){
                return createCache(key);
            }
        });
private static final String KEY = "key";
private void getCache() {
    //1.查询缓存,没有返回null
    List<Integer> list = cache.getIfPresent(KEY);
    //2.查找缓存,不存在生成缓存,生成失败返回null
    list = cache.get(KEY, k -> createCache(KEY));
    //3.添加或者更新一个缓存元素
    cache.put(KEY, list);
    //4.移除一个缓存元素
    cache.invalidate(KEY);
}

4.2 自动加载Loading Cache:LoadingCache比Cache多了如果缓存不存在,会通过CacheLoader.load生成对应的缓存数据到缓存中,实现自动加载。

LoadingCache<String, List<Integer>> loadingCache = Caffeine.newBuilder()
        .maximumSize(500)
        .build(key -> createCache(key));

private void getLoadingCache() {
    //1.查找缓存,不存在生成缓存,生成失败返回null
    List<Integer> list = loadingCache.get(KEY);
    //2.批量查找缓存,如果缓存不存在则生成缓存
    List<String> requestKeys = new ArrayList<>();
    Map<String, List<Integer>> map = loadingCache.getAll(requestKeys);
}

4.3 手动异步加载Async Cache:AsyncCache是Cache异步形式,提供了Executor生成缓存并返回CompletableFuture的能力。默认的线程池实现是 ForkJoinPool.commonPool() 。也可以使用Caffeine.executo设置自定义的线程池。

AsyncCache<String, List<Integer>> asyncCache = Caffeine.newBuilder()
        .maximumSize(500)
        .buildAsync();
 
private void getAsyncCache() {
    //1.查询缓存,没有返回null
    CompletableFuture<List<Integer>> graph = asyncCache.getIfPresent(KEY);
    //2.查找缓存,如果不存在,异步生成
    graph = asyncCache.get(KEY, k -> createCache(KEY));
    //3.添加或者更新一个缓存元素
    asyncCache.put(KEY, graph);
    //4.移除一个缓存元素
    asyncCache.synchronous().invalidate(KEY);
}

4.4 自动异步加载Async Loading Cache:AsyncLoadingCache是LoadingCache的异步形式,返回一个包含取值的CompletableFuture。

AsyncLoadingCache<String, List<Integer>> asyncLoadingCache = Caffeine.newBuilder()
            .maximumSize(500)
            .buildAsync(key->{
              log.info("缓存不存在异步加载");
              return createCache(key);
            });
//查找不存在异步生成
CompletableFuture<Graph> graph = cache.get(key);
//批量查找不存在异步生成
CompletableFuture<Map<Key, Graph>> graphs = cache.getAll(keys);

5、驱逐策略

       Caffeine提供三类驱逐策略:基于大小、基于时间、基于引用。

5.1 基于大小

//1:个数(大小)
LoadingCache<String, List<Integer>> loadingCache = Caffeine.newBuilder()
        .maximumSize(500)
        .build();
//2.基于缓存内元素权重
LoadingCache<String, List<Integer>> loadingCache = Caffeine.newBuilder()
        .maximumWeight(200)
        .weigher((String key, List<Integer> list) -> list.size())
        .build();

备注:maximumWeight 与 maximumSize 不可以同时使用。

5.2 基于时间

//1.设置写缓存后n秒钟过期      
LoadingCache<String, List<Integer>> loadingCache = Caffeine.newBuilder()
        .expireAfterWrite(10, TimeUnit.SECONDS)
        .build();       
 
//2.设置读写缓存后n秒钟过期,类似于Guava Cache的expireAfterWrite    
LoadingCache<String, List<Integer>> loadingCache = Caffeine.newBuilder()
        .expireAfterAccess(10, TimeUnit.SECONDS)
        .build();
 
//3.自定义策略需要自己实现Expiry接口。
LoadingCache<String, List<Integer>> loadingCache = Caffeine.newBuilder()
        .expireAfter(new Expiry<String, St
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值