代码经验---Java本地缓存解决方案01:用Google的CacheBuilder实现

 

原创:https://www.cnblogs.com/andychou/p/8342007.html

 

为什么是本地缓存,而不是分布式的集群缓存?

         目前的数据,大多是业务无关的小数据缓存,没有必要搞分布式的集群缓存,目前涉及到订单和商品的数据,会直接走DB进行请求,再加上分布式缓存的构建,集群维护成本比较高,不太适合紧急的业务项目。

 

本地缓存在那个区域?

         目前考虑的是占用了JVM的heap区域,再细化一点的就是heap中的old区,目前的数据量来看,都是一些小数据,加起来没有几百兆,放在heap区域最快最方便。后期如果需要放置在本地缓存的数据大的时候,可以考虑在off-heap区域,但是off-heap区域的话,需要考虑对象的序列化(因为off-heap区域存储的是二进制的数据),另外一个的话就是off-heap的GC问题。其实,如果真的数据量比较大,那其实就可以考虑搞一个集中式的缓存系统,可以是单机,也可以是集群,来承担缓存的作用。

 

有哪些本地缓存:

EhCache来构建缓存、引入guava的cacheBuilder来构建缓存(

Guava CacheConcurrentMap很相似,但也不完全一样。

最基本的区别是ConcurrentMap会一直保存所添加的元素,直到显式的移除

Guava Cache为了限制内存的占用,通常都是设定为自动回收元素。在某些场景下,尽管LoadingCahe不回收元素,但是它还是很有用的,因为它会自动加载缓存。

Guava Cache适用场景:

  • 你愿意消耗一部分内存来提升速度;
  • 你已经预料某些值会被多次调用;
  • 缓存数据不会超过内存总量;

Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。整体上来说Guava cache 是本地缓存的不二之选,简单易用,性能好

 

集群内部,缓存的一致性如何保证?

如果采用ehcache的话,可以使用框架本身的JGroup来实现组内机器之间的缓存同步。

如果是采用google的cacheBuilder的话,需要自己实现缓存的同步。

A、非实时生效数据:数据的更新不会时时发生,应用启动的时候更新即可,然后定时程序定时去清理缓存;

B、需要实时生效数据:启动时可预热也可不预热,但是缓存数据变更后,集群之间需要同步

 

本地缓存

一般来说我们可以直接使用jdk里提供的数据结构来作为缓存,但这样有个问题就是缓存的一些机制,比如缓存过期的淘汰策略,缓存的初始化,缓存最大容量的设置,缓存的共享等等一些列的问题需要自己去考虑和实现

第二种方法就是我们可以使用一些业界开源的,成熟的一些第三方的工具来帮助我们实现缓存。这其中有:EHCache,cahce4j等等好多框架和工具。但从我使用的来看我认为google里guava包内的缓存工具是我使用过的最方便,简单的缓存框架。

下面就来介绍这个Guava包内的CacheBuilder。

 

注意:Guava Cache是单个应用运行时的本地缓存,单机版的缓存。它不把数据存放到文件或外部服务器。如果这不符合你的需求,请尝试Memcached或Redis;

@Component
public class LocalCache {

    private static final CopyOnWriteArraySet<Integer> COPY_ON_WRITE_ARRAY_SET = new CopyOnWriteArraySet<>();

    private static final Cache<String, Object> CACHE = CacheBuilder.newBuilder().build();

    public void cache(String key, Object value) {
        CACHE.put(key, value);
    }

    public Object getCache(String key) {
        Object value = CACHE.getIfPresent(key);
        CACHE.invalidate(key);
        return value;
    }

    public void putSet(int type) {
        COPY_ON_WRITE_ARRAY_SET.add(type);
    }

    public boolean ifExist(int type) {
        return COPY_ON_WRITE_ARRAY_SET.contains(type);
    }

    public boolean removeSet(int type) {
        return COPY_ON_WRITE_ARRAY_SET.remove(type);
    }

    public static CopyOnWriteArraySet<Integer> getCopyOnWriteArraySet() {
        return COPY_ON_WRITE_ARRAY_SET;
    }
}


@Slf4j
public class LocalCacheLock {


    private String lockKey;

    private Object lock;

    private static Cache<String, Object> cache = CacheBuilder.newBuilder().build();

    public LocalCacheLock(int s1, int s2) {
        this.lockKey = s1 + "--" + s2;
        Object value = cache.getIfPresent(lockKey);
        if (value == null) {
            this.lock = s1 + "--" + s2;
            cache.put(lockKey, this.lock);
        } else {
            this.lock = value;
        }
    }

    public void lock() {
        synchronized (lock) {
            try {
                lock.wait(5000);
            } catch (InterruptedException e) {
                log.error("thread was interrupted:", e);
            }
        }
    }

    public void unLock() {
        synchronized (lock) {
            lock.notifyAll();
        }
    }

    public String getLockKey() {
        return lockKey;
    }
}


简单使用:

        localCache.putSet(key);

        LocalCacheLock lock = new LocalCacheLock( aaaa, bbbb);
        // 业务代码
        。。。。
        lock.lock(); // 锁定等待
        localCache.getCache(lock.getLockKey());

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值