欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Guava缓存项目实战

程序员文章站 2022-07-13 17:37:18
...

项目中涉及到数据缓存,对一致性要求还行,本来打算用Guava做。后来发现6台机器且数据量3亿左右,内存大小和路由达不到要求。换成redis做缓存,但是guava代码已经初步写好,放在此处用于记录。

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉Guava缓存处理抽象类
 *
 * @author wangzha
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public abstract class AbstractGuavaCache<K, V> {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGuavaCache.class);

    /**
     * loadingCache 核心实例
     */
    private volatile LoadingCache<K, V> loadingCache;

    /**
     * 并发级别
     */
    private int concurrencyLevel;

    /**
     * 缓存超时时间
     */
    private long expireTime;

    /**
     * 初始容量
     */
    private int initialCapacity;

    /**
     * 最大容量
     */
    private long maxSize;

    protected AbstractGuavaCache(int concurrencyLevel, long expireTime, int initialCapacity, long maxSize) {
        this.concurrencyLevel = concurrencyLevel;
        this.expireTime = expireTime;
        this.initialCapacity = initialCapacity;
        this.maxSize = maxSize;
    }

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉
     *
     * @Param
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     **/
    public LoadingCache<K, V> getCache() {
        // 双重检查锁-防止重复加载
        if (loadingCache == null) {
            synchronized (this) {
                if (loadingCache == null) {
                    loadingCache = CacheBuilder.newBuilder()
                            // 设置并发级别为8
                            .concurrencyLevel(concurrencyLevel)
                            // 设置多久不读缓存废弃
                            .expireAfterAccess(expireTime, TimeUnit.HOURS)
                            // 设置初始条数
                            .initialCapacity(initialCapacity)
                            // 设置最大条数,超过则按照LRU策略淘汰缓存
                            .maximumSize(maxSize)
                            // 设置要统计缓存的命中率
                            .recordStats()
                            // 设置缓存的移除通知
                            .removalListener(removalNotification -> {
                                if (LOGGER.isDebugEnabled()) {
                                    LOGGER.debug("{} was moved,cause is {}", removalNotification.getKey(),
                                            removalNotification.getCause());
                                }
                            }).build(
                                    // 设置缓存不存在时,自动加载入缓存
                                    new CacheLoader<K, V>() {
                                        @Override
                                        public V load(K k) throws Exception {
                                            return fetchData(k);
                                        }
                                    });
                }
            }
        }
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("本地缓存{}初始化成功", this.getClass().getSimpleName());
        }
        return loadingCache;
    }

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉载入数据
     *
     * @Param
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     **/
    protected abstract V fetchData(K k);

    public int getConcurrencyLevel() {
        return concurrencyLevel;
    }

    public void setConcurrencyLevel(int concurrencyLevel) {
        this.concurrencyLevel = concurrencyLevel;
    }

    public long getExpireTime() {
        return expireTime;
    }

    public void setExpireTime(long expireTime) {
        this.expireTime = expireTime;
    }

    public int getInitialCapacity() {
        return initialCapacity;
    }

    public void setInitialCapacity(int initialCapacity) {
        this.initialCapacity = initialCapacity;
    }

    public long getMaxSize() {
        return maxSize;
    }

    public void setMaxSize(long maxSize) {
        this.maxSize = maxSize;
    }
}
/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉默认Guava缓存管理类
 *
 * @author wangzha
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class DefaultGuavaCacheManage {

    public static final Logger LOGGER = LoggerFactory.getLogger(DefaultGuavaCacheManage.class);

    /**
     * 缓存包装
     */
    private static AbstractGuavaCache<String, Object> wrapper;

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉初始化缓存容器
     *
     * @Param
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     **/
    @SuppressWarnings("unchecked")
    public static boolean initGuaveCache() {
        wrapper = DefaultGuavaCache.getInstance();
        if (wrapper != null) {
            return true;
        } else {
            LOGGER.error("Fail to init Guava Cache !");
            return false;
        }
    }

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉通过key获取缓存值
     * 
     * @Param key 缓存key
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     **/
    public static Object get(String key) {
        Object object = null;
        try {
            object = wrapper.getCache().get(key);
        } catch (ExecutionException e) {
            LOGGER.error("get Guava cache exception");
        }
        return object;
    }

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉通过key获取缓存值,如果没有采取一定措施
     * 
     * @Param key 缓存的key
     * @return callable 回调函数
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     **/
    public static Object getOrDo(String key, Callable callable) {
        Object object = null;
        try {
            wrapper.getCache().get(key, callable);
        } catch (ExecutionException e) {
            LOGGER.error("getOrDo Guava cache exception");
        }
        return object;
    }

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉清除指定key缓存
     * 
     * @Param key 缓存的key
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     **/
    public static void invalidate(String key) {
        wrapper.getCache().invalidate(key);
    }

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉清除所有缓存
     *
     * @Param
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     **/
    public static void inalidateAll(){
        wrapper.getCache().invalidateAll();
    }

    /**
     * 静态内部类实现单例
     * 
     * @param <String>
     * @param <Object>
     */
     static class DefaultGuavaCache<String, Object> extends AbstractGuavaCache<String, Object> {

        private static AbstractGuavaCache guavaCache = new DefaultGuavaCache(
                CacheScmCfg.getInteger(CacheScmCfg.DEFAULT_GUAVA_CONCURRENCY_LEVEL_KEY),
                CacheScmCfg.getInteger(CacheScmCfg.DEFAULT_GUAVA_EXPIRE_TIME_KEY),
                CacheScmCfg.getInteger(CacheScmCfg.DEFAULT_GUAVA_INITIALCAPACITY_KEY),
                CacheScmCfg.getInteger(CacheScmCfg.DEFAULT_GUAVA_MAXSIZE_KEY));

        public static AbstractGuavaCache getInstance() {
            return guavaCache;
        }

        private DefaultGuavaCache(int concurrencyLevel, long expireTime, int initialCapacity, long maxSize) {
            super(concurrencyLevel, expireTime, initialCapacity, maxSize);
        }

        @Override
        protected Object fetchData(String s) {
            //具体操作
            return null;
        }
    }
}
相关标签: 缓存 guava