关于缓存:Caffeine本地缓存实战

89次阅读

共计 2742 个字符,预计需要花费 7 分钟才能阅读完成。

简介

Caffeine 是一个高性能 Java 缓存库,提供近乎最佳的命中率。

A Cache 相似于 ConcurrentMap,但不完全相同。最基本的区别是 ConcurrentMap 保留所有增加到它的元素,直到它们被显式删除。Cache 另一方面,A 通常配置为主动驱赶条目,以限度其内存占用。在某些状况下,a LoadingCacheorAsyncLoadingCache 可能很有用,即便它不驱赶条目,因为其自​​动缓存加载

性能

Caffeine 提供灵便的结构来创立具备以下性能组合的缓存:

主动将条目加载到缓存中,可选异步
当超过基于频率和早先度的最大值时基于大小的驱赶
基于工夫的条目过期,自上次访问或上次写入以来测量
当条目标第一个古老申请产生时异步刷新
键主动包装在弱援用中
值主动包装在弱援用或软援用中
驱赶(或以其余形式删除)条目标告诉
写入流传到内部资源
缓存拜访统计的累积

应用

1.pom.xml 依赖

            <!--caffeine 本地缓存 -->
            <dependency>
                <groupId>com.github.ben-manes.caffeine</groupId>
                <artifactId>caffeine</artifactId>
                <version>2.9.1</version>
            </dependency>

2. 初始化缓存

你也能够基于以下,做降级,比方做异步操作 …

/**
 * @description Caffeine 本地缓存
 * @author: yx-0173
 * @date: 2021-07-15 10:23
 **/
@Configuration
@Slf4j
public class CacheConfig {

    @Bean
    public Cache<String, Object> cache() {return Caffeine.newBuilder()
                // 设置最初一次写入或拜访后通过固定工夫过期
                .expireAfterWrite(60, TimeUnit.SECONDS)
                // 监听器
                .removalListener((String key, Object graph, RemovalCause cause) ->
                        log.info("移除缓存中 key 为:{},value 为:{}的缓存记录", key, graph))
                // 初始的缓存空间大小
                .initialCapacity(100)
                // 缓存的最大条数
                .maximumSize(1000)
                .build();}
   
   // api 测试,以下代码不要写道这个配置类,可自行整顿
   
   // 查找条目,如果未找到,则为 null
   cache.getIfPresent(key);
   // 从缓存中查问,如果查问不到则将对应的值放入缓存,如果不可计算,则为 null
   cache.get(key, k - > createExpensiveGraph(key));
   // 插入或批改缓存
   cache.put(key, graph);
   // 依据 key 删除一个缓存
   cache.invalidate(key);
   // 批量获取
   cache.getAll(keys);。。。还有很多,可自行官网,页尾附上官网地址
}

3. 工具类奉献给大家

**
 * @description 本地缓存工具类
 * @author: yx-0173
 * @date: 2021-07-15 12:51
 **/
@Component
public class CacheUtil<K, V> {

    @Resource
    private Cache<K, V> cache;

    /**
     * 依据 key 获取 value
     *
     * @return Object
     */
    public V get(K key) {return cache.asMap().get(key);
    }

    /**
     * 依据 key 获取 value
     *
     * @return Object
     */
    public Map<? extends K, ? extends V> getBatch(List<String> key) {return cache.getAllPresent(key);
    }

    /**
     * 将一个 map 插入
     */
    public void putBatch(Map<? extends K, ? extends V> map) {cache.asMap().putAll(map);
    }


    public ConcurrentMap<K, V> get() {return cache.asMap();
    }

    /**
     * 插入缓存
     *
     * @param key   key
     * @param value value
     */
    public void put(K key, V value) {cache.put(key, value);
    }

    /**
     * 插入缓存, 如果不存在,则将 value 放入缓存
     *
     * @param key   key
     * @param value value
     */
    public V getIfNotExist(K key, V value) {return cache.get(key, k -> value);
    }

    /**
     * 是否含有
     *
     * @param key key
     */
    public boolean contains(K key) {return cache.asMap().containsKey(key);
    }

    /**
     * 革除
     */
    public void deleteAll() {cache.invalidateAll();
    }

    /**
     * 批量删除
     *
     * @param key key
     */
    public void delete(List<String> key) {cache.invalidateAll(key);
    }

    /**
     * 删除
     *
     * @param key key
     */
    public void delete(K key) {cache.asMap().remove(key);
    }

    /**
     * 更新
     *
     * @param key   key
     * @param value value
     */
    public void update(K key, V value) {cache.put(key, value);
    }
}

Caffeine 驱赶策略

1. 基于大小

Size-based

// 依据缓存中的条目数驱赶
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
    .maximumSize(10_000)
    .build(key -> createExpensiveGraph(key));

// 依据缓存中的顶点数驱赶
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
    .maximumWeight(10_000)
    .weigher((Key key, Graph graph) -> graph.vertices().size())
    .build(key -> createExpensiveGraph(key));

学习之道,永无止境,要学习如何以渔,不要学如何以鱼。
Caffeine 官网:https://github.com/ben-manes/…

正文完
 0