堆缓存 — Guava Cache/Ehcache/MapDB

目录

一、Java缓存类型

二、Guava Cache/Ehcache/MapDB堆内缓存对比

三、代码实例

1. 依赖jar包

2. Cache定义

3. 调用实例

三、参考资料


一、Java缓存类型

类型优点缺点组件适用场景注意
堆内缓存

速度最快

1.受JVM堆大小限制

2.JVM重启时数据消失

Guava Cache、

Ehcache、

MapDB

热点数据、

数据量少

1.存储软弱引用对象

2.无需序列化/反序列化

堆外缓存速度较慢

1.受机器内存大小限制

2.机器重启时数据消失

Ehcache、

MapDB

相对热的数据需序列化/反序列化
磁盘缓存数据不会丢失

速度很慢

Ehcache、

MapDB

不热的数据需序列化/反序列化
分布式缓存大量数据缓存速度最慢

Redis、

Ehcache + Terracotta

全量数据

1.可单机、可集群

2.需序列化/反序列化

二、Guava Cache/Ehcache/MapDB堆内缓存对比

类型描述Guava CacheEhcacheMapDB
并发量并发线程数.concurrencyLevel.withDispatcherConcurrency.concurrencyScale
条目回收缓存最大条目.maximumSize.heap(100, EntryUnit.ENTRIES).expireMaxSize
TTL回收存活期失效.expireAfterWrite(10, TimeUnit.SECONDS).withExpiry(
ExpiryPolicyBuilder.timeToLiveExpiration(
Duration.ofSeconds(10)))

.expireAfterCreate

/.expireAfterUpdate

TTI回收空闲期失效.expireAfterAccess(10, TimeUnit.SECONDS).withExpiry(
ExpiryPolicyBuilder.timeToIdleExpiration(
Duration.ofSeconds(10)))
.expireAfterGet
主动失效主动删除

.invalidate

/.invalidateAll

.remove

/.removeAll

.remove

/.clear

触发失效被动删除PUT时缓存清理

PUT时缓存清理

/定义线程池处理

PUT时缓存清理

/定义线程池处理

命中统计缓存命中率.recordStats------------
其他

1.Guava Cache只有堆内缓存;定义软弱引用对象:软引用.softValues/弱引用.weakValues;

2.Ehcache提供堆内、堆外、磁盘、分布式缓存,集群功能不完善;若是集群建议Redis;

3.MapDB提供堆内、堆外、磁盘缓存,且提供事务支持;

三、代码实例

1. 依赖jar包

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

<dependency>
   <groupId>org.ehcache</groupId>
   <artifactId>ehcache</artifactId>
   <version>3.5.2</version>
</dependency>

<dependency>
   <groupId>org.mapdb</groupId>
   <artifactId>mapdb</artifactId>
   <version>3.0.8</version>
</dependency>

2. Cache定义

package com.common.instance.test.config.heapcache;

import com.common.instance.test.dao.WcPendantTabDao;
import com.common.instance.test.entity.WcPendantTab;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.spi.loaderwriter.CacheLoaderWriter;
import org.mapdb.DBMaker;
import org.mapdb.HTreeMap;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @description 堆内缓存
 * @author tcm
 * @version 1.0.0
 * @date 2021/11/5 17:27
 **/
@Component
public class HeapCache {

    // Guava Cache缓存
    private static LoadingCache<String, List<WcPendantTab>> guavaCache;
    // Ehcache Cache缓存
    private static Cache<String, List<WcPendantTab>> ehcacheCache;
    // MapDB Cache缓存
    private static HTreeMap mapDBCache;
    // 业务处理
    private static WcPendantTabDao wcPendantTabDao;

    @Resource
    public void setWcPendantTabDao(WcPendantTabDao wcPendantTabDao) {
        HeapCache.wcPendantTabDao = wcPendantTabDao;
    }

    public HeapCache(){
        getGuavaCache();
        getEhcacheCache();
        getMapDBCache();
    }

    // 初始化Guava Cache缓存
    public static LoadingCache<String, List<WcPendantTab>> getGuavaCache(){
        if (Objects.isNull(guavaCache)) {
            guavaCache = CacheBuilder.newBuilder()
                    // 并发数量
                    .concurrencyLevel(4)
                    // TTL设置
                    .expireAfterWrite(10, TimeUnit.SECONDS)
                    // 缓存容量,超出按LRU回收
                    .maximumSize(10000)
                    // 软引用,弱引用weakValues
                    .softValues()
                    // 缓存统计
                    .recordStats()
                    // 缓存没有命中,则读DB
                    .build(new CacheLoader<String, List<WcPendantTab>>() {
                        @Override
                        public List<WcPendantTab> load(String mgdbId) throws Exception {
                            WcPendantTab tab = new WcPendantTab();
                            tab.setMgdbId(mgdbId);
                            return wcPendantTabDao.queryAll(tab);
                        }
                    });
        }
        return guavaCache;
    }

    // 初始化Ehcache Cache缓存
    public static Cache<String, List<WcPendantTab>> getEhcacheCache(){
        if (Objects.isNull(ehcacheCache)) {
            CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true);

            CacheConfigurationBuilder cacheConfig = CacheConfigurationBuilder
                    .newCacheConfigurationBuilder(String.class, List.class,
                            ResourcePoolsBuilder.newResourcePoolsBuilder()
                                    .heap(100, EntryUnit.ENTRIES)) // 堆内缓存
                    .withDispatcherConcurrency(4)
                    // 过期配置
                    .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(10)))
                    // 缓存没有命中,则读DB
                    .withLoaderWriter(new CacheLoaderWriter<String, List>() {
                        @Override
                        public List load(String mgdbId) throws Exception {
                            WcPendantTab tab = new WcPendantTab();
                            tab.setMgdbId(mgdbId);
                            return wcPendantTabDao.queryAll(tab);
                        }

                        @Override
                        public void write(String s, List list) throws Exception {

                        }

                        @Override
                        public void delete(String s) throws Exception {

                        }
                    });

            ehcacheCache = cacheManager.createCache("myEhcacheCache", cacheConfig);
        }

        return ehcacheCache;
    }

    // 初始化MapDB缓存
    public static HTreeMap<String, List<WcPendantTab>> getMapDBCache(){
        if (Objects.isNull(mapDBCache)) {
            mapDBCache = DBMaker
                    // 对缓存
                    .heapDB()
                    // 并发数
                    .concurrencyScale(4).make().hashMap("myMapDBCache")
                    // 最大缓存条目
                    .expireMaxSize(10000)
                    // 过期时间
                    .expireAfterCreate(10, TimeUnit.SECONDS)
                    .expireAfterUpdate(10, TimeUnit.SECONDS)
                    .expireAfterGet(10, TimeUnit.SECONDS)
                    .create();
        }
        return mapDBCache;
    }

}

3. 调用实例

package com.common.instance.test.service.impl;

import com.common.instance.test.config.heapcache.HeapCache;
import com.common.instance.test.dao.WcPendantTabDao;
import com.common.instance.test.entity.WcPendantTab;
import com.common.instance.test.service.WcPendantTabService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

/**
 * Tab菜单(WcPendantTab)表服务实现类
 *
 * @author tcm
 * @since 2021-01-14 15:02:08
 */
@Service
public class WcPendantTabServiceImpl implements WcPendantTabService {

    @Resource
    private WcPendantTabDao wcPendantTabDao;

    @Override
    public List<WcPendantTab> queryAll(String mgdbId){
        List<WcPendantTab> wcPendantTabs = null;
        try {
            // Cache-As-SoR模式
            // 获取Guava Cache缓存的数据
            wcPendantTabs = HeapCache.getGuavaCache().get(mgdbId);
            // 获取Ehcache Cache缓存的数据
            wcPendantTabs = HeapCache.getEhcacheCache().get(mgdbId);

            // Cache-Aside模式
            // 获取MapDB缓存的数据
            wcPendantTabs = HeapCache.getMapDBCache().get(mgdbId);
            if (Objects.isNull(wcPendantTabs)) {
                WcPendantTab tab = new WcPendantTab();
                tab.setMgdbId(mgdbId);
                wcPendantTabs = wcPendantTabDao.queryAll(tab);

                // 写到缓存
                HeapCache.getMapDBCache().put(mgdbId, wcPendantTabs);
            }
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return wcPendantTabs;
    }

}

三、参考资料

Guava Cache用法介绍_qianshanding0708的博客-CSDN博客

Ehcache(03)——Ehcache中储存缓存的方式_Elim的博客-CSDN博客

MapDb学习笔记_SmileJosiah的博客-CSDN博客

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Guava Cache是Google Guava库中提供的一种本地缓存解决方案。它是一个基于内存的缓存,可以在应用程序内部存储数据,提高应用程序性能。 Guava Cache提供了以下特性: 1. 自动加载:当缓存中不存在某个键的值时,可以自动加载生成该值。 2. 自动移除:缓存中的某些条目可以在一定时间内自动过期,或者可以使用大小限制来限制缓存中的条目数。 3. 针对不同的缓存数据设置不同的过期时间、存活时间、最大值、最小值等。 4. 支持同步和异步缓存。 使用Guava Cache非常简单,只需要按以下步骤操作: 1. 引入Guava库。 2. 创建一个CacheBuilder对象,用于配置缓存。 3. 调用build()方法创建一个Cache对象。 4. 使用put()方法向缓存中添加数据。 5. 使用get()方法从缓存中读取数据,如果缓存中不存在该键对应的值,则可以自动加载。 6. 使用invalidate()方法从缓存中移除数据。 下面是一个简单的示例: ```java import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; public class GuavaCacheExample { public static void main(String[] args) throws ExecutionException { // 创建一个CacheBuilder对象 CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder() .maximumSize(100) // 设置缓存最大条目数 .expireAfterWrite(10, TimeUnit.MINUTES); // 设置缓存过期时间 // 创建一个Cache对象 LoadingCache<String, String> cache = cacheBuilder.build(new CacheLoader<String, String>() { @Override public String load(String key) throws Exception { System.out.println("loading " + key); // 自动加载数据 return "value-" + key; } }); // 添加数据到缓存cache.put("key1", "value1"); cache.put("key2", "value2"); // 从缓存中读取数据 System.out.println(cache.get("key1")); // 输出"value1" System.out.println(cache.get("key3")); // 输出"loading key3"和"value-key3" // 移除缓存中的数据 cache.invalidate("key1"); System.out.println(cache.get("key1", () -> "default")); // 输出"default" } } ``` 在这个示例中,我们使用CacheBuilder对象配置了缓存的最大条目数和过期时间。我们还使用CacheLoader对象创建了一个自动加载的缓存,当缓存中不存在某个键的值时,可以自动加载生成该值。我们使用put()方法向缓存中添加了两个数据,使用get()方法从缓存中读取了两个数据,并使用invalidate()方法从缓存中移除了一个数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值