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;

@Componentpublic 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;    }}  @Slf4jpublic 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()); 

原网址: 访问
创建于: 2023-02-22 09:53:15
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论