基于guava实现本地缓存

今天一个接口响应超时,然后我优化,用到了本地缓存。

maven 依赖

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>27.1-jre</version>
    </dependency>

LocalCache 本地缓存工具类

package com.itbac.common.cache;

import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

/**
 * 本地缓存工具
 *
 * <br/>对于一些改动频率低且调用非常频繁,可加上本地有效时间短(1分钟)的二级缓存
 *
 * @author Bac
 *
 * @Date 2020年1月6日 下午12:12:12
 */
public class LocalCache<K,V> {

    /**默认的本地缓存最大数据长度*/
    private static final long Default_Maximum_Size = 5_000;
    /**本地缓存数据长度为1    */
    private static final long Single_Size = 1;

    /**写入本地缓存后的失效时间秒数*/
    private static final long Max_Expire_After_Write = 1 * 60;

    private Cache<K, Optional<V>> cache;

    private LocalCache(){}

    /**
     * 创建本地缓存对象(创建此对象后,需要用static成员变量进行唯一初始化引用)
     * (默认为一分钟缓存)
     * @return
     */
    public static <K,V> LocalCache<K,V> create() {
        LocalCache<K,V> local = new LocalCache<K,V> ();

        local.cache =  CacheBuilder.newBuilder()
                .maximumSize(Default_Maximum_Size)
                .expireAfterWrite(Max_Expire_After_Write, TimeUnit.SECONDS)
                .build();
        return local;
    }

    /**
     * 创建本地缓存对象
     * @param expireAfterWrite 写入缓存后失效的秒数
     * @return
     */
    public static <K,V> LocalCache<K,V> create(long expireAfterWrite) {
        LocalCache<K,V> local = new LocalCache<K,V> ();

        local.cache =  CacheBuilder.newBuilder()
                .maximumSize(Default_Maximum_Size)
                .expireAfterWrite(expireAfterWrite <= 0 ?  Max_Expire_After_Write : expireAfterWrite, TimeUnit.SECONDS)
                .build();
        return local;
    }

    /**
     * 创建只能缓存一个数据元素的本地缓存对象
     * @return
     */
    public static <K,V> LocalCache<K,V> createSingleSize() {
        LocalCache<K,V> local = new LocalCache<K,V> ();

        local.cache =  CacheBuilder.newBuilder()
                .maximumSize(Single_Size)
                .expireAfterWrite(Max_Expire_After_Write, TimeUnit.SECONDS)
                .build();
        return local;
    }

    private Cache<K, Optional<V>> getCache() {
        return this.cache;
    }

    /**
     * 获取缓存k对应的值,没有值返回null
     * @param k       缓存key
     * @return
     */
    public Optional<V> get(K k) {
        return getCache().getIfPresent(k);
    }

    /**
     * 获取缓存key对应的值,若key未在本地缓存中,使用call进行初始化
     * @param k          缓存key
     * @param call    若key未在本地缓存中,使用call进行初始化。
     *                可用Lambada表达式, () ->{ 具体逻辑,return V };
     * @return
     */
    public V get(K k,Supplier<V> call) {
        if (k == null) {
            return null;
        }
        /**
         * 由于Guava的Callable接口中,若采用过期机制,
         * 如果自带的Callable返回了null,get(xx,CallAble)便会抛出异常: CacheLoader returned null for key
         * 故采用Optional + 额外的Supplier
         */
        Optional<V>  value = get(k);
        //未放置本地缓存数据
        if (value == null) {
            V v =  call.get();
            getCache().put(k, Optional.ofNullable(v));
            return v;
        }
        return value.orElse(null);
    }
}

使用本地缓存

package com.itbac.common.cache;

import java.util.ArrayList;
import java.util.List;

public class SkuQueryService {

    //本地缓存,写入后20秒失效
    private static final LocalCache<String, List<String>> Cache = LocalCache.create(20);

    public static void main(String[] args) {

        //使用本地缓存
        List<String> list = Cache.get("key", () -> {
            //具体获取数据的逻辑
            List<String> strings = new ArrayList<>();
            strings.add("假装有数据");
            return strings;
        });

    }
}

设置缓存后,要等到了时间,缓存才会失效。需要容忍一段时间的数据不一致。

原文地址:https://www.cnblogs.com/itbac/p/12159157.html

时间: 2024-08-30 10:56:35

基于guava实现本地缓存的相关文章

使用guava cache再本地缓存热点数据

某些热点数据在短时间内可能会被成千上万次访问,所以除了放在redis之外,还可以放在本地内存,也就是JVM的内存中. 我们可以使用google的guava cache组件实现本地缓存,之所以选择guava是因为它可以控制key和value的大小和超时时间,可以配置LRU策略且guava是线程安全的. 首先引入guava cache <dependency> <groupId>com.google.guava</groupId> <artifactId>gua

关于java中的本地缓存-总结概述

java中的本地缓存,工作后陆续用到,一直想写,一直无从下手,最近又涉及到这方面的问题了,梳理了一下.自己构造单例.guava.ehcache基本上涵盖了目前的大多数行为了.   为什么要有本地缓存? 在 系统中,有些数据,数据量小,但是访问十分频繁(例如国家标准行政区域数据),针对这种场景,需要将数据搞到应用的本地缓存中,以提升系统的访问效率,减 少无谓的数据库访问(数据库访问占用数据库连接,同时网络消耗比较大),但是有一点需要注意,就是缓存的占用空间以及缓存的失效策略. 为什么是本地缓存,而

Java8简单的本地缓存实现

译文出处: 踏雁寻花   原文出处:lukaseder 这里我将会给大家演示用ConcurrentHashMap类和lambda表达式实现一个本地缓存.因为Map有一个新的方法,在key为Null的时候自动计算一个新的value值.非常适合实现cache.来看下代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static void main(String[] args) {     for (int i = 0; i < 10; i++)   

分布式系统JVM本地缓存同步实现dlcache

现成的分布式K/V缓存已经有很多的实现,最主要的比如redis,memcached.那为什么我们还要自己去实现呢,在我们解决了分布式系统下大量rpc调用导致的高延时后,我们发现很多服务需要大量的访问分布式缓存,由于分布式缓存通常部署在单独的服务器中,在lan中,通常单次网络也需要1ms,一个请求少的可能需要一两次缓存访问,复杂的服务比如委托.出入金.融资等会访问一二十次,即使程序已经优化,但仅访问分布式缓存花费的网络延时占据了整个响应时间的很大一部分比例,而这些需要广泛被访问的数据通常数据量本身

图片下载本地缓存时间戳显示图片方法

来源:http://ask.dcloud.net.cn/article/511 源码下载 参考文章http://ask.dcloud.net.cn/article/256http://ask.dcloud.net.cn/article/397 说明:为了方便,里面使用的图片来源是从上面文章中的源码项目获取的.说明:参考了上面文章中的思路,然后自己重新写了一个较为完整的图片本地缓存显示工具.功能1.第一次显示图片时下载到本地,然后之后如果本地存在缓存(根据url),则显示本地缓存的图片2. 基于p

A comparison of local caches (1) 【本地缓存之比较 (1)】

1. Spring local cache   [Spring 本地缓存] Spring provided cacheable annotation since 3.1. It's very super convinient to use and can obviously boost application performance. 从3.1版本开始,Spring提供了cacheable注解.它使用起来非常方便,还可以很明显的提升应用性能.具体的,怎么使用呢? First, create a

Java学习之ConcurrentHashMap实现一个本地缓存

ConcurrentHashMap融合了Hashtable和HashMap二者的优势. Hashtable是做了线程同步,HashMap未考虑同步.所以HashMap在单线程下效率较高,Hashtable在多线程下同步操作能保证程序的正确性.  但是Hashtable每次执行同步操作都需要锁住整个结构. ConcurrentHashMap的出现就是为了解决Hashtable同步lock整个数据结构的问题.ConcurrentHashMap锁的方式是细颗粒度. ConcurrentHashMap将

java应用中的本地缓存

java中的本地缓存,工作后陆续用到,一直想写,一直无从下手,最近又涉及到这方面的问题了,梳理了一下.自己构造单例.guava.ehcache基本上涵盖了目前的大多数行为了. 为什么要有本地缓存?在 系统中,有些数据,数据量小,但是访问十分频繁(例如国家标准行政区域数据),针对这种场景,需要将数据搞到应用的本地缓存中,以提升系统的访问效率,减 少无谓的数据库访问(数据库访问占用数据库连接,同时网络消耗比较大),但是有一点需要注意,就是缓存的占用空间以及缓存的失效策略. 所谓的本地混存是相对于网络

Java本地缓存解决方案其一(使用Google的CacheBuilder)

前不久,业务实现上需要用到本地缓存来解决一些数据量相对较小但是频繁访问的数据,通过查找各种资料,找到了一种可以实现的方案--采用的是Google的CacheBuilder.下面是代码实现过程:1.首先在maven中引入下面的包: <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</versio