zoukankan      html  css  js  c++  java
  • google的CacheBuilder缓存

    适用性:

    计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存。

    常用用法:

    LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
    .maximumSize(1000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .removalListener(MY_LISTENER)
    .build(
    new CacheLoader<Key, Graph>() {
    public Graph load(Key key) throws AnyException {
    return createExpensiveGraph(key);
    }
    });

    项目中用法:

    private LoadingCache<QueryEptAdsInfoVo, String> eptAdsInfoCache =CacheBuilder.newBuilder().softValues().maximumSize(5000).expireAfterWrite(1,TimeUnit.MINUTES)
    .build(new CacheLoader<QueryEptAdsInfoVo,String>() {
    @Override
    public String load(final QueryEptAdsInfoVo tmp) throws Exception {
      //代码逻辑
    }
    });

    之前常用 ConcurrentMap来做缓存,那它们有什么区别呢?

    Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素,可设置过期时间。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。

    三种基于时间的清理或刷新缓存数据的方式:
    expireAfterAccess: 当缓存项在指定的时间段内没有被读或写就会被回收。
    expireAfterWrite:当缓存项在指定的时间段内没有更新就会被回收。
    refreshAfterWrite:当缓存项上一次更新操作之后的多久会被刷新。
     
    考虑到时效性,我们可以使用expireAfterWrite,使每次更新之后的指定时间让缓存失效,然后重新加载缓存。guava cache会严格限制只有1个加载操作,这样会很好地防止缓存失效的瞬间大量请求穿透到后端引起雪崩效应。
         然而,通过分析源码,guava cache在限制只有1个加载操作时进行加锁,其他请求必须阻塞等待这个加载操作完成;而且,在加载完成之后,其他请求的线程会逐一获得锁,去判断是否已被加载完成,每个线程必须轮流地走一个“”获得锁,获得值,释放锁“”的过程,这样性能会有一些损耗。这里由于我们计划本地缓存1秒,所以频繁的过期和加载,锁等待等过程会让性能有较大的损耗。
     
         因此我们考虑使用refreshAfterWrite。refreshAfterWrite的特点是,在refresh的过程中,严格限制只有1个重新加载操作,而其他查询先返回旧值,这样有效地可以减少等待和锁争用,所以refreshAfterWrite会比expireAfterWrite性能好。但是它也有一个缺点,因为到达指定时间后,它不能严格保证所有的查询都获取到新值。了解过guava cache的定时失效(或刷新)原来的同学都知道,guava cache并没使用额外的线程去做定时清理和加载的功能,而是依赖于查询请求。在查询的时候去比对上次更新的时间,如超过指定时间则进行加载或刷新。所以,如果使用refreshAfterWrite,在吞吐量很低的情况下,如很长一段时间内没有查询之后,发生的查询有可能会得到一个旧值(这个旧值可能来自于很长时间之前),这将会引发问题。
     
         可以看出refreshAfterWrite和expireAfterWrite两种方式各有优缺点,各有使用场景。那么能否在refreshAfterWrite和expireAfterWrite找到一个折中?比如说控制缓存每1s进行refresh,如果超过2s没有访问,那么则让缓存失效,下次访问时不会得到旧值,而是必须得待新值加载。由于guava官方文档没有给出一个详细的解释,查阅一些网上资料也没有得到答案,因此只能对源码进行分析,寻找答案。经过分析,当同时使用两者的时候,可以达到预想的效果,这真是一个好消息呐!
     
    Guava Cache是单个应用运行时的本地缓存,单机版的缓存。它不把数据存放到文件或外部服务器。如果这不符合你的需求,请尝试Memcached或Redis
  • 相关阅读:
    Halcon各个算子角度计算方式汇总
    阈值分割算子之OSTU算法
    Halcon18--深度学习应用问题记录
    Halcon18新技术
    Halcon之3D重建
    关于数组排序(顺序,逆序)
    封装jq的ajax
    h5在微信生成分享海报(带二维码)
    使用mintUI的总结
    时间戳转日期
  • 原文地址:https://www.cnblogs.com/ngy0217/p/8795634.html
Copyright © 2011-2022 走看看