Java 缓存介绍(Caffeine,EhCache)

本文对比了Caffeine和Ehcache两种缓存框架,阐述了Caffeine的高效策略和易用性优势,以及Ehcache的全面功能。通过性能测试,Caffeine在写操作上表现优异。适用于追求性能的项目选择。
摘要由CSDN通过智能技术生成

Caffeine

一个高性能的缓存库,Caffeine 使用 Window TinyLfu 回收策略,可以提供了一个近乎最佳的命中率

依赖

maven

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.5.5</version>
</dependency>

Grade

compile 'com.github.ben-manes.caffeine:caffeine:2.5.5'
基本用法
		@Test
    public void baseTest() {
        Cache<String, Data> cache = Caffeine.newBuilder()
            // 设置过期时间
            .expireAfterWrite(1, TimeUnit.MINUTES)
            // 缓存数量
            .maximumSize(100).build();
        // 往缓存中设置 
        cache.put("A", new Data("A"));
        Assert.assertEquals(cache.getIfPresent("A").getData(), "A");
        // 取值 若存在返回 不存在返回null
        Data b = cache.getIfPresent("B");
        Assert.assertNull(b);
        // 取值 若不存在 则按后面计算并返回
        b = cache.get("B", k -> new Data(k));
        Assert.assertEquals(cache.getIfPresent("B").getData(), "B");
        // 手动移除key
        cache.invalidate("A");
        Assert.assertNull(cache.getIfPresent("A"));
    }
同步加载
		@Test
    public void syncLoadTest() {
        LoadingCache<String, Data> cache = Caffeine.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(1, TimeUnit.MINUTES)
                .build(k -> new Data(k));
        //这个获取的仍然为空
        Assert.assertNull(cache.getIfPresent("A"));
        // get() 检索值 此处会根据初始化时指定的方法初始化value
        Data a = cache.get("a");
        Assert.assertNotNull(a);
        Assert.assertEquals(a.getData(),"a");
    }
异步加载
		@Test
    public void asyncLoadTest() {
        AsyncLoadingCache<String, Data> cache = Caffeine.newBuilder().maximumSize(100).expireAfterWrite(1, TimeUnit.MINUTES).buildAsync(k -> new Data(k));
        cache.get("A").thenAccept(data -> {
            Assert.assertNotNull(data);
            Assert.assertEquals(data.getData(), "a");
        });
    }

这3种加载方式使用的Cache类不同,可以根据自己的需求来选择合适的方式来加载数据

回收策略
  1. 基于maximumSize()设置的大小,若果超过最大值后将异步回收

  2. 基于权重大小删除元素

    1. .maximumWeight():指定缓存的最大容量,当缓存超出这个容量的时候,会使用Window TinyLfu策略来删除缓存
    2. .weighter((k,v)->{}):计算权重方法
    3. maximumWeight与maximumSize不可以同时使用。
  3. 基于时间回收

    1. 访问后到期 — 从上次读或写发生后,条目即过期
    2. 写入后到期 — 从上次写入发生之后,条目即过期
    3. 自定义策略 — 到期时间由 Expiry 实现独自计算
  4. 基于引用

    我们可以将缓存的驱逐配置成基于垃圾回收器。为此,我们可以将key 和 value 配置为弱引用或只将值配置成软引用。

    • Caffeine.weakKeys():使用弱引用存储key。如果没有其他地方对该key有强引用,那么该缓存就会被垃圾回收器回收。
    • Caffeine.weakValues():使用弱引用存储value。
    • Caffeine.softValues():使用软引用存储value。当内存满了过后,软引用的对象以将使用最近最少使用(least-recently-used ) 的方式进行垃圾回收。

Ehcache

​ Ehcache 从 Hibernate 发展而来,逐渐涵盖了 Cahce 界的全部功能,是目前发展势头最好的一个项目。具有快速,简单,低消耗,依赖性小,扩展性强,支持对象或序列化缓存,支持缓存或元素的失效,提供 LRU、LFU 和 FIFO 缓存策略,支持内存缓存和磁盘缓存,分布式缓存机制等等特点。

功能
  • 支持内存及磁盘存储
  • 多种缓存策略
  • 支持多缓存管理器实例,以及一个实例的多个缓存区域
缓存淘汰策略
  • FIFO:先进先出
  • LFU:最少被使用,缓存的元素有一个hit属性,hit值最小的将会被清出缓存
  • LRU:最近最少使用,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存
依赖
maven 
<dependency>
      <groupId>org.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>3.7.0</version>
</dependency>
gradle
compile 'org.ehcache:ehchache:3.7.0'
基本用法
public class EhCache implements LocalCache<String, Data> {
    private CacheManager        cacheManager;
    private Cache<String, Data> cache;
    public EhCache() {
        // 创建缓存管理器 一个缓存管理器可以关联多个缓存
        cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
        // 初始化
        cacheManager.init();
        // 创建 dataCache缓存
        CacheConfigurationBuilder builder = CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Data.class, ResourcePoolsBuilder.heap(100));
        cache = cacheManager.createCache("dataCache", builder);
    }
    @Override
    public Data get(String K) {
        return cache.get(K);
    }
    @Override
    public void set(String K, Data data) {
        cache.put(K, data);
    }
}

2种缓存框架对比

特性

​ 从支持的功能上来看,ehcache支持的功能特性更多一些,比如多级缓存,分布式缓存,缓存监听器等等。但如果只是想简单的使用一个内存缓存组件,并且对性能有较高的要求时,可以优先考虑Caffeine,它的性能比ehcache更好,并且它使用了更加优秀的缓存淘汰策略,提供接近理想的命中率,在Spring5中已经作为基础的缓存组件使用了。

易用性

​ 从我简单使用上来看,Caffeine提供的api更友好一些,而且ehcache似乎没有提供异步加载特性。配置也略微烦琐了些。

性能

1 读多写少场景

测试条件

1.缓存1000个数据

2.8个线程读 2个线程写

Caffeine(读/写)Ehcache(读/写)
11558360022/1847731561794188434/155912462
21861119523/2884436761818122432/147250831
31421957913/2778566681348268819/142143289
平均1613812486/2503578331653526561/148435527
2 只读场景

测试条件

1.缓存1000个数据

2.10个线程读

Caffeine(读)Ehcache(读)
117236282252129962082
218990308852025097805
321246126642086497546
平均19157572582080519144

只读场景下Caffeine性能比Ehcache略微差一些。

总结

​ 在读性能上两者差距不大,但在写性能上Caffeine明显比Ehcache要高出不少。综合易用性,性能来看,我认为一般项目使用Caffeine就足够了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值