美文网首页springboot进阶
Caffeine的基础使用

Caffeine的基础使用

作者: 农民工进城 | 来源:发表于2020-09-27 10:32 被阅读0次

    一、简介

    Caffeine是基于Java 8的高性能接近最佳的缓存工具库。Caffeine使用Google Guava启发的API提供内存缓存。所以它的使用成本较低,跟Guava的API大致一致。

    它主要有以下几个功能:

    二、常见API

    Cache分为LoadingCache(同步缓存),AsyncLoadingCache(异步缓存)。

    • pom 依赖
            <dependency>
                <groupId>com.github.benmanes.caffeine</groupId>
                <artifactId>caffeine</artifactId>
                <version>2.8.5</version>
            </dependency>
    
    2.1 人工加载策略
    Cache<Object, Object> cache = Caffeine.newBuilder()
            .expireAfterWrite(1, TimeUnit.SECONDS)
                .expireAfterAccess(1, TimeUnit.SECONDS)
            .maximumSize(10)//最大条数
            .build();//定义cache
    
    User user1=(User) cache.get(id, v-> userDao.getOne(id));//如果cache不存在,查询数据库
    
    2.2 自动加载同步
      LoadingCache<String, User> userDaoCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.SECONDS)
                .expireAfterAccess(1, TimeUnit.SECONDS).maximumSize(10).build(key -> userDao.getOne(key))
    
        User user = userDaoCache.get("1");
    
    2.3 自动加载异步
      AsyncLoadingCache<String, User> asynUserDaoCache = Caffeine.newBuilder()
                .expireAfterWrite(1, TimeUnit.SECONDS).expireAfterAccess(1, TimeUnit.SECONDS).maximumSize(10)
                .buildAsync(key -> userDao.getOne(key));
    
      User user = asynUserDaoCache.get("1").get();
    

    三、其他API

    3.1 统计缓存信息
    Cache<Object, Object> cacheStats = Caffeine.newBuilder()
                .expireAfterWrite(1000, TimeUnit.SECONDS)
                .expireAfterAccess(1000, TimeUnit.SECONDS)
                 .recordStats()//记录统计信息
                .weakKeys()//key弱引用
                .weakValues()//value 弱引用
                .maximumSize(10).build()
    
    CacheStats stats = cacheStats.stats();//获取统计信息
    
    3.2 CacheWriter
        LoadingCache<String, User> cacheWriter = Caffeine.newBuilder().expireAfterAccess(3, TimeUnit.SECONDS)
                .writer(new CacheWriter<String, User>() {
                    @Override
                    public void write(String id, User user) {
                        System.out.println("***写入***" + id);//当混存数据时,调用此方案
                    }
    
                    @Override
                    public void delete(String id, User user, RemovalCause cause) {
                        System.out.println("***delete***" + id);//当手动删除数据时,调用此方法
                    }
                }).build(id -> userDao.getOne(id));
    
    3.3RemovalListener监听(手动删除)
            LoadingCache<String, User> removalListener = Caffeine.newBuilder()
                .removalListener(new RemovalListener<String, User>() {
    
                    @Override
                    public void onRemoval(@Nullable String key, @Nullable User value, @NonNull RemovalCause cause) {
                        System.out.println(key + "*****" + value);
                    }
                }).expireAfterAccess(3, TimeUnit.SECONDS).build(id -> userDao.getOne(id));
    

    四、缓存淘汰机制

    常见缓存机制有:LRU(Least Recently Used)最近最少使用跟LFU(Least Frequently Used)最不经常使用。

    4.1 LRU
    • LRU:如果一个数据在最近一段时间没有被访问到,那么认为在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰
    • 缺点:注重对数据的使用时间上是不是最近。缓存数目超过容量,缓存数据很容易被淘汰。
    4.2 LFU
    • LFU:如果一个数据在最近一段时间很少被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最小频率访问的数据最先被淘汰
    • 缺点:注重对元素的使用频次上是不是较大。
      1.在短时间内如果某些元素访问频率很高,会导致后续很难淘汰,造成无效数据缓存。
      2.突发流量的时候,可能由于没有及时达到足够的频率数据来保证自己驻留在缓存中,从而导致缓存的命中率下降
    4.3 W-TinyLFU

    为了弥补LRU跟LFU的不足与缺点,产生了W-TinyLFU算法。
    W-TinyLFU算法大致思想:缓存有窗口缓存跟主缓存两部门组成。窗口缓存没有淘汰策略,从而解决了突发流量时不达标不缓存的问题。而TinyLFU维护了近期访问记录的频率信息,作为一个过滤器,当新记录来时,只有满足TinyLFU要求的记录才可以被插入缓存,也因此解决了缓存超过容量轻易淘汰问题。

    caffeine采用的就是这种策略。对算法的具体过程感兴趣,可以自行网上找资料了解下。

    五、参数总结

    maximumSize:设置缓存最大条目数,超过条目则触发回收 
    maximumWeight:设置缓存最大权重,设置权重是通过weigher方法, 需要注意的是权重也是限制缓存大小的参数,并不会影响缓存淘汰策略,也不能和maximumSize方法一起使用。 
    weakKeys:将key设置为弱引用,在GC时可以直接淘汰
    weakValues:将value设置为弱引用,在GC时可以直接淘汰
    softValues:将value设置为软引用,在内存溢出前可以直接淘汰
    expireAfterWrite:写入后隔段时间过期
    expireAfterAccess:访问后隔断时间过期
    refreshAfterWrite:写入后隔断时间刷新
    removalListener:缓存淘汰监听器,配置监听器后,每个条目淘汰时都会调用该监听器
    writer:writer监听器其实提供了两个监听,一个是缓存写入或更新是的write,一个是缓存淘汰时的delete,每个条目淘汰时都会调用该监听器
    
    

    相关文章

      网友评论

        本文标题:Caffeine的基础使用

        本文链接:https://www.haomeiwen.com/subject/gbmkuktx.html