转载

Caffeine LoadingCache用法详解

  1. 缓存
  2. 异步持续更新缓存

构造LoadingCache对象

LoadingCache<Integer, String> loadingCache = Caffeine.newBuilder()
                .expireAfterWrite(1, TimeUnit.SECONDS)
                .refreshAfterWrite(500, TimeUnit.MILLISECONDS)
                .maximumSize(10) // 缓存最大数量
                .removalListener((RemovalListener<Integer, String>) (integer, s, removalCause) -> {
                    System.out.println("key:" + integer + " value:" + s + " cause:"+removalCause);
                })
                .build(new CacheLoader<Integer, String>() {
                    @Nullable
                    @Override
                    public String load(@NonNull Integer i) throws Exception {
                        return i.toString();
                    }

                    @Override
                    public Map<Integer, String> loadAll(Iterable<? extends Integer> keys) {
                        Map<Integer, String> map = new HashMap<>();
                        for (Integer i : keys) {
                            map.put(i, i.toString());
                        }
                        return map;
                    }
                });
复制代码

参数解析

  • expireAfterWrite:失效策略,类似参数还有expireAfterAccess,key的缓存时间到期以后并不会被立即删除,caffeine使用惰性删除的策略,在LoadingCache被修改,如添加,更新等,或者该失效的key被访问的时候才会删除。
  • refreshAfterWrite:刷新策略,设置为比写入时间小可以保证缓存永不失效,对于某些场景,比如请求频率低但是耗时长的业务来说,自动刷新能够显著提升效率和体验
  • maximumSize:缓存的item的最大数目,如果超过这个数, caffeine将根据Window TinyLfu策略淘汰一些key,类似的参数还有maximumWeight,示例代码如下,设置maximumWeight的同时,要设置weigher参数,根据key生成对应的weight,如果累计weight达到了maximumWeight,将会进行key的淘汰,淘汰策略与maximumSize一样,与weight无关。另外,maximumSize与maximumWeight不能同时使用,否则会报IllegalStateException。
LoadingCache<Integer, String> weightLoadingCache = Caffeine.newBuilder()
                .maximumWeight(1000)
                .weigher((Weigher<Integer, String>) (integer, s) -> integer)
                .build(new CacheLoader<Integer, String>() {
                    @Nullable
                    @Override
                    public String load(@NonNull Integer integer) throws Exception {
                        return null;
                    }
                });
复制代码
  • removalListener:当缓存被移除的时候执行的策略,例如打日志等
  • build参数CacheLoader:用于refresh时load缓存的策略,根据具体业务而定,建议在实现load方法的同时实现loadAll方法loadAll方法适用于批量查缓存的需求,或者刷新缓存涉及到网络交互等耗时操作。比如你的缓存数据需要从redis里获取,如果不实现loadAll,则需要多次load操作,也就需要多次redis交互,非常耗时,而实现loadAll,则可以在loadAll里向redis发送一条批量请求,显著降低网络交互次数和时间,显著提升效率。

注意事项

caffeine是不缓存null值的,如果在load的时候返回null,caffeine将会把对应的key从缓存中删除,同时,loadAll返回的map里是不可以包含value为null的数据,否则将会报NullPointerException

常用方法

V get(@NonNull K key)

返回给定的key在LoadingCache中的数据,如果cache中没有该key,将调用CacheLoader的load方法去load数据,如果load不到数据,将返回null。

Map<K, V> getAll(@NonNull Iterable<? extends K> keys)

返回keys中的key的缓存数据,组合成map,如果某个key或某些key在缓存中不存在,将会调用loadAll去load数据,loadAll仍然无法load到数据的key,将不会put到返回的map里。

原文  https://juejin.im/post/5d7796e5e51d4561fb04bfdf
正文到此结束
Loading...