Google Guava 内存缓存

1.引入Maven - 版本自行选择最新

<dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
       <version>19.0</version>
 </dependency>

2.案例 - [ 部分核心代码 ]

import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.apache.log4j.Logger;

import java.util.concurrent.TimeUnit;

public class MemoryCacheUtils {

    private final static Logger logger = Logger.getLogger(MemoryCacheUtils.class);

    private static LoadingCache<Long, MyResult> myMemoryCache = null;

    static{
        myMemoryCache = CacheBuilder.newBuilder()     //CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例
                .concurrencyLevel(500)                   //设置并发级别为8,并发级别是指可以同时写缓存的线程数
                .expireAfterWrite(10, TimeUnit.MINUTES)  //设置写缓存后10分钟过期
                .refreshAfterWrite(1, TimeUnit.SECONDS)  //设置写缓存后1秒钟刷新
                .initialCapacity(500)                    //设置缓存容器的初始容量为5
                .maximumSize(10000)                      //设置缓存最大容量为10000,超过10000之后就会按照LRU最近虽少使用算法来移除缓存项
                .recordStats()                           //设置要统计缓存的命中率
//            .removalListener(new RemovalListener<Object, Object>() { //设置缓存的移除通知
//                @Override
//                public void onRemoval(RemovalNotification<Object, Object> notification) {
//                    System.out.println("内存缓存:"+notification.getKey() + " 被移除了,原因: " + notification.getCause());
//                }
//            })
                .build(//build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
                        new CacheLoader<Long, MyResult>() {
                            @Override
                            public MyResult load(Long key) throws Exception {
//                          System.out.println("缓存没有时,从数据库加载" + key);
//                                return new MyResult();
                                return null;
                            }
                        }
                );
    }

    public static void putCache(Long skuId,MyResult video){
        myMemoryCache.put(skuId,video);
    }

    public static MyResult getCache(Long skuId){
        try{
            return myMemoryCache.get(skuId);
        }catch(Exception e){
            if(e instanceof CacheLoader.InvalidCacheLoadException){
                logger.error(String.format("缓存中没有该值:%s [%s]",e.getMessage(),skuId));
            }else{
                logger.error(String.format("通过内存缓存获取失败:%s [%s]",e.getMessage(),skuId),e);
            }
            return null;
        }
    }


    public static void main(String[] args) throws Exception {

        MyResult result = MemoryCacheUtils.getCache(123L);
        System.out.println(JSONObject.toJSONString(result));

        MyResult cache = new MyResult();
        TraceVideoData data = new TraceVideoData();
        data.setSkuId(123L);
        cache.setData(data);
        cache.setResult(esult_Status.SUCCESS);
        MemoryCacheUtils.putCache(123L,cache);

        result = MemoryCacheUtils.getCache(123L);
        System.out.println(JSONObject.toJSONString(result));

        System.out.println("size:"+MemoryCacheUtils.myMemoryCache.size());
    }

}

LoadingCache是不支持缓存null值的;如果load回调方法返回null,则在get的时候会抛出异常 - 需要程序捕获处理;

3.缓存移除机制

guava做cache时候数据的移除分为被动移除主动移除两种。

被动移除分为三种:

  1. 基于大小的移除:数量达到指定大小,会把不常用的键值移除

  2. 基于时间的移除:expireAfterAccess(long, TimeUnit) 根据某个键值对最后一次访问之后多少时间后移除
            expireAfterWrite(long, TimeUnit) 根据某个键值对被创建或值被替换后多少时间移除

  3. 基于引用的移除:主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除

        主动移除分为三种:1).单独移除:Cache.invalidate(key)

                 2).批量移除:Cache.invalidateAll(keys)

                 3).移除所有:Cache.invalidateAll()

        如果配置了移除监听器RemovalListener,则在所有移除的动作时会同步执行该listener下的逻辑。

        如需改成异步,使用:RemovalListeners.asynchronous(RemovalListener, Executor)

4.说明

        在项目中大家经常使用redis作为缓存,但是在某些高并发的场景下redis也会出现瓶颈 造成热key等因素致使redis链接超时导致整个业务线超时,所有必填的情况下添加内存缓存可以大大缓解压力使业务更稳定;

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值