caffeine本地缓存的使用和详解

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 在项目中我们经常使用缓存架构,来缓存我们的数据,比如redis、caffeine等。那么redis和caffeine有什么区别?作用又有哪些不同呢?

在项目中我们经常使用缓存架构,来缓存我们的数据,比如redis、caffeine等。那么redis和caffeine有什么区别?作用又有哪些不同呢?

caffeine详情

redis和caffeine的区别?

相同点就不用说,广义上都是缓存的方式。咱们就说说不同。

  • redis是将数据存储到内存里;caffeine是将数据存储在本地应用里
  • caffeine和redis相比,没有了网络IO上的消耗

那么在高并发场景中,一般我们都是结合使用,形成一二级缓存。caffeine作为一级缓存,redis作为二级缓存。
使用流程大致如下:去一级缓存中查找数据(caffeine-本地应用内)如果没有的话,去二级缓存中查找数据(redis-内存)再没有,再去数据库中查找数据(数据库-磁盘)。
在这里插入图片描述

caffeine的使用

Caffeine 相当于一个缓存工厂,可以创建出多个缓存实例 Cache。这些缓存实例都继承了 Caffeine 的参数配置,Caffeine 是如何配置的,这些缓存实例就具有什么样的特性和功能。
Caffeine 是目前性能最好的本地缓存,因此,在考虑使用本地缓存时,直接选择 Caffeine 即可。

Caffeine.newBuilder().maximumSize(6000).expireAfterAccess(10, TimeUnit.MINUTES)
                .expireAfterWrite(10, TimeUnit.MINUTES).removalListener(new RemovalListener<String, CacheUserInfo>() {

                    @Override
                    public void onRemoval(@Nullable String key, @Nullable CacheUserInfo value,
                            @NonNull RemovalCause cause) {
                        if (value != null) {
                            log.info("user profile has removed. uid {}, name {}", key, value.getName());
                        }
                    }
                }).recordStats().build(new CacheLoader<String, CacheUserInfo>() {

                    @Override
                    public @Nullable CacheUserInfo load(@NonNull String telephone) throws Exception {

                        try {
                            return CacheUserInfo.getLoggedUserProfile(telephone, false);
                        } catch (Exception e) {
                            log.error("load user profile error", e);
                            return null;
                        }
                    }

                });

    }

caffeine缓存属性

initialCapacity 缓存初始容量

整数,表示能存储多少个缓存对象。
为什么要设置初始容量呢?因为如果提前能预估缓存的使用大小,那么可以设置缓存的初始容量,以免缓存不断地进行扩容,致使效率不高。

maximumSize 最大容量

如果缓存中的数据量超过这个数值,Caffeine 会有一个异步线程来专门负责清除缓存,按照指定的清除策略来清除掉多余的缓存。注意:比如最大容量是 2,此时已经存入了2个数据了,此时存入第3个数据,触发异步线程清除缓存,在清除操作没有完成之前,缓存中仍然有3个数据,且 3 个数据均可读,缓存的大小也是 3,只有当缓存操作完成了,缓存中才只剩 2 个数据,至于清除掉了哪个数据,这就要看清除策略了。

maximumWeight 最大权重

存入缓存的每个元素都要有一个权重值,当缓存中所有元素的权重值超过最大权重时,就会触发异步清除。下面给个例子。

class Student{
        Integer score;
        String name;
}
    Caffeine<String, Student> caffeine = Caffeine.newBuilder()
            .maximumWeight(100)
            .weigher((String key, Person value)-> value.getScore());
    Cache<String, Student> cache = caffeine.build();
    cache.put("one", new Student(40, "one"));
    cache.put("two", new Student(60, "two"));
    cache.put("three", new Student(50, "three"));
    Thread.sleep(10);
    System.out.println(cache.estimatedSize());
    System.out.println(cache.getIfPresent("two"));
    

运行结果:

2
null

要使用权重来衡量的话,就要规定权重是什么,每个元素的权重怎么计算,weigher 方法就是设置权重规则的,它的参数是一个函数,函数的参数是 key 和 value,函数的返回值就是元素的权重,比如上述代码中,caffeine 设置了最大权重值为 100,然后将每个 Student对象的 socre成绩作为权重值,所以整个意思就是:缓存中存储的是 Student对象,但是限制所有对象的 score总和不能超过 100,否则就触发异步清除缓存。

特别要注意一点:最大容量 和 最大权重 只能二选一作为缓存空间的限制。

CacheStats 默认的缓存状态收集器

默认情况下,缓存的状态会用一个 CacheStats 对象记录下来,通过访问 CacheStats 对象就可以知道当前缓存的各种状态指标,那究竟有哪些指标呢?
先说一下什么是“加载”,当查询缓存时,缓存未命中,那就需要去第三方数据库中查询,然后将查询出的数据先存入缓存,再返回给查询者,这个过程就是加载。

caffeine 过期策略

在Caffeine中分为两种缓存,一个是有界缓存,一个是无界缓存,无界缓存不需要过期并且没有界限。在有界缓存中提供了三个过期API:

  1. expireAfterWrite:代表着写了之后多久过期。(上面列子就是这种方式)
  2. expireAfterAccess:代表着最后一次访问了之后多久过期。
  3. expireAfter:在expireAfter中需要自己实现Expiry接口,这个接口支持create,update,以及access了之后多久过期。注意这个API和前面两个API是互斥的。这里和前面两个API不同的是,需要你告诉缓存框架,他应该在具体的某个时间过期,也就是通过前面的重写create,update,以及access的方法,获取具体的过期时间。

caffeine 更新策略

何为更新策略?就是在设定多长时间后会自动刷新缓存。

Caffeine提供了refreshAfterWrite()方法来让我们进行写后多久更新策略:

    LoadingCache<String, String> build = CacheBuilder.newBuilder().
                refreshAfterWrite(1, TimeUnit.DAYS).build(new CacheLoader<String, String>() {
        @OverridepublicString
        load(String key) {
            return "";
        }
    });
}

caffeine 打点监控

在Caffeine中提供了一些的打点监控策略,通过recordStats()Api进行开启,默认是使用Caffeine自带的,也可以自己进行实现。在StatsCounter接口中,定义了需要打点的方法目前来说有如下几个:

  1. recordHits:记录缓存命中
  2. recordMisses:记录缓存未命中
  3. recordLoadSuccess:记录加载成功(指的是CacheLoader加载成功)
  4. recordLoadFailure:记录加载失败
  5. recordEviction:记录淘汰数据

通过上面的监听,我们可以实时监控缓存当前的状态,以评估缓存的健康程度以及缓存命中率等,方便后续调整参数。

caffeine 淘汰监听

有很多时候我们需要知道Caffeine中的缓存为什么被淘汰了呢,从而进行一些优化?这个时候我们就需要一个监听器,代码如下所示:

Cache<String, String> cache = Caffeine.newBuilder().removaListener(((key, value, cause) -> {
    System.out.println(cause);
})).build();

在Caffeine中被淘汰的原因有很多种:

  1. EXPLICIT: 这个原因是,用户造成的,通过调用remove方法从而进行删除。
  2. REPLACED: 更新的时候,其实相当于把老的value给删了。
  3. COLLECTED: 用于我们的垃圾收集器,也就是我们上面减少的软引用,弱引用。
  4. EXPIRED:过期淘汰。
  5. SIZE: 大小淘汰,当超过最大的时候就会进行淘汰。
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
缓存 算法 Java
Caffeine Cache~高性能 Java 本地缓存之王
Caffeine Cache~高性能 Java 本地缓存之王
85 1
|
XML 缓存 NoSQL
玩转Spring Cache --- 整合进程缓存之王Caffeine Cache和Ehcache3.x【享学Spring】(下)
玩转Spring Cache --- 整合进程缓存之王Caffeine Cache和Ehcache3.x【享学Spring】(下)
|
6月前
|
缓存 NoSQL Java
Redis+Caffeine 两级缓存(二)
Redis+Caffeine 两级缓存
389 0
|
6月前
|
存储 缓存 NoSQL
Redis+Caffeine 两级缓存(一)
Redis+Caffeine 两级缓存
211 0
|
7月前
|
缓存 Java Spring
缓存 - Spring Boot 整合 Caffeine 不完全指北
缓存 - Spring Boot 整合 Caffeine 不完全指北
164 0
|
7月前
|
存储 缓存 监控
缓存 - Caffeine 不完全指北
缓存 - Caffeine 不完全指北
77 0
缓存 - Caffeine 不完全指北
|
9月前
|
缓存 NoSQL 算法
LRU算法与Caffeine、Redis中的缓存淘汰策略详解与比较
在实际应用中,我们需要考虑数据访问模式、内存限制以及性能需求等因素来选择最合适的缓存淘汰策略。通过深入了解LRU算法及其在不同缓存库中的应用,我们可以更好地优化我们的应用程序的性能。
256 1
|
存储 缓存 Java
Spring Boot集成Caffeine Cache时遇到获取到的缓存对象和当初设置的对象不同的问题...
Spring Boot集成Caffeine Cache时遇到获取到的缓存对象和当初设置的对象不同的问题...
221 0
|
存储 缓存 Java
【Caffeine】高性能缓存库,万字详解教程
大家在做项目时,遇到的第一个问题就是如何提高服务器的性能,从而提升用户的体验。当遇到这个问题时,不可避免的就会引出了 `缓存` 这个概念。 而 `缓存`(主要从服务端介绍) 又分 本地缓存 和 分布式缓存 以及 数据库缓存 。这三种缓存分别适应不同的场景,这里我们先介绍一下本地缓存。 说到本地缓存,就不得不说到 `caffeine`,caffeine 被称之为缓存之王。它为什么被这么多人推崇呢?这离不开它的高性能。
505 1
|
存储 缓存 NoSQL
玩转Spring Cache --- 整合进程缓存之王Caffeine Cache和Ehcache3.x【享学Spring】(上)
玩转Spring Cache --- 整合进程缓存之王Caffeine Cache和Ehcache3.x【享学Spring】(上)
玩转Spring Cache --- 整合进程缓存之王Caffeine Cache和Ehcache3.x【享学Spring】(上)