本地缓存Caffeine使用教程

一、Caffeine介绍

1. 什么是Caffeine

Caffeine是一个基于Java1. 8的高性能本地缓存库。它提供了灵活的缓存配置选项,如缓存大小限制、过期策略、驱逐策略等。Caffeine是由guava演变而来的,性能和内存占用都优于guava,它的底层数据存储采用ConcurrentHashMap,从功能上可以将Caffeine视为带有淘汰策略的ConcurrentHashMap。

官方介绍及源码详见:Caffeine的Github网址

2. 为什么要用Caffeine

1.自动加载和异步刷新:
Caffeine支持缓存项的自动加载和刷新。当缓存项过期或不存在时,Caffeine 可以配置为异步的刷新该缓存项,从而提高应用程序的响应性。通过注解的方式我们很容易就能实现存量代码的缓存,对代码侵入性低,而且简单方便。
2.灵活的缓存策略:
Caffeine提供了基于大小和频率/最近使用情况的多种逐出策略(后面会提到),从而提高缓存的命中率。
3.高性能、线程安全:
Caffeine使用了ConcurrentHashMap等数据结构来提供高性能的缓存操作,并且支持多线程场景。通过减少锁竞争和上下文切换,Caffeine能够实现高吞吐量的缓存访问。
4.内存友好:
①Caffeine使用弱引用自动包装键:这样当没有其他强引用指向这些键时,它们可以被垃圾回收器回收。这有助于减少内存占用,并允许缓存自动释放不再需要的条目。
②Caffeine使用弱引用或软引用自动包装值:与键类似,缓存值也可以自动包装在弱引用或软引用中。弱引用值在没有其他强引用时会被回收,而软引用值则会在内存不足时被回收。这为缓存提供了额外的灵活性,允许它在内存压力下自动释放部分数据。
5.访问速度快:
相比分布式缓存,本地缓存访问速度更快,能够减少网络I/O开销。

3. Caffeine使用的缓存淘汰策略

1.默认使用W-TinyLFU:
W-TinyLFU(Weighted Tiny Least Frequently Used)结合了LRU(Least Recently Used,最近最少使用)和LFU(Least FrequentlyUsed,最不经常使用)的优点。它通过记录访问频率并使用对数计数器来避免对LFU的偏置,从而提供更加准确的缓存淘汰策略。这种策略能够在多种场景下提供接近理论最优的缓存性能。
2.基于时间的过期策略:
①TTL(Time to Live):根据缓存项的存活时间来进行过期策略。可以设置缓存项的过期时间,当缓存项超过指定的时间后,将会被自动移除。
②TTR(Time to Refresh):在缓存项最后一次访问一段时间后进行自动清理。
3.基于大小的淘汰策略:
根据缓存项的大小来进行淘汰策略。可以设置缓存的最大大小,当缓存的大小超过指定的阈值时,将会按照一定的算法淘汰一部分缓存项。
4.基于引用的淘汰策略:
根据缓存项的引用情况来进行淘汰策略。可以选择强引用、软引用或弱引用作为缓存项的引用类型,当JVM对缓存项的引用不再存在时,将会自动移除缓存项。
5.基于权重的淘汰策略:
根据缓存项的权重来进行淘汰策略。可以为每个缓存项设置权重,当缓存的总权重超过指定的阈值时,将会按照一定的算法淘汰一部分缓存项。
6.自定义淘汰策略:
Caffeine还允许用户通过实现特定的接口来定义自己的淘汰策略,以满足特定应用场景的需求。

4. Caffeine的应用场景

1.常用数据缓存:
对于需要频繁访问但又不会频繁变更的数据,如配置信息、枚举值(如类目)等,可以使用Caffeine进行缓存,以减少对数据库或其他存储系统的访问,提高数据读取速度。
2.实时性要求不高的数据缓存:
对于实时性要求不高的场景,如某些统计信息、历史数据,可以使用Caffeine进行缓存。这些数据的变更频率相对较低,即使缓存中的数据不是最新的,也不会对业务产生太大的影响。
3.多级缓存:
可以结合Redis等远程缓存作为多级缓存使用,在数据量较大的场景使用,本地缓存未命中再查Redis,Redis未命中再查DB。这样能大大减小Redis的缓存压力。

5. Caffeine的局限性

1.数据共享与一致性
数据共享限制:本地缓存Caffeine是与应用程序在同一个进程内的内存空间中存储数据,因此它只能被该应用程序进程访问,而不能被其他应用程序进程或节点共享。这意味着在集群部署的环境中,每个应用节点都需要维护自己的本地缓存,难以实现数据的高效共享。
数据一致性难题:当数据库中的数据发生更新时,需要同步更新所有服务器节点上的本地缓存,以保证数据的一致性。然而,这一过程操作复杂且容易出错,特别是在集群部署的环境中,数据同步的难度和成本显著增加。
2.存储能力与扩展性
存储能力有限:本地缓存占用了应用进程的内存空间,因此其存储能力受到应用程序进程内存大小的限制。当需要缓存的数据量较大时,本地缓存可能无法满足需求。
扩展性不足:本地缓存的存储能力无法随着应用程序的扩展而扩展。在应用程序需要处理更多数据或更多用户请求时,本地缓存可能成为性能瓶颈。
3.持久化与可靠性
数据易丢失:本地缓存的数据存储在应用程序进程的内存空间中,因此当应用程序进程重启或崩溃时,本地缓存的数据会丢失。这可能导致数据不一致或丢失重要的缓存数据。
缺乏持久化机制:与分布式缓存相比,本地缓存通常没有内置的持久化机制来将数据持久化到磁盘或其他存储介质上。这意味着在应用程序重启或崩溃后,无法恢复之前缓存的数据。

二、Caffeine使用教程

1.基础版

①引入依赖
首先,需要在项目中引入Caffeine的依赖。如果使用Maven作为构建工具,可以在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>适配的版本号</version>
</dependency>

注意:jdk11以上的用3.x版本,如果是1.8请用2.x版本。

②创建缓存实例
使用Caffeine库提供的API,可以创建一个缓存实例。在创建缓存实例时,可以指定缓存的最大容量、过期策略等参数。例如:

Cache<String, String> cache = Caffeine.newBuilder()
    .maximumSize(100) // 设置缓存的最大条目数
    .expireAfterWrite(10, TimeUnit.MINUTES) // 设置缓存项在写入后10分钟过期
    .build();

③向缓存中添加数据
使用缓存实例的put方法,可以将数据添加到缓存中。例如:

cache.put("key1", "value1");

④获取缓存中的数据
使用缓存实例的get或getIfPresent方法,可以根据键获取缓存中的数据。get方法会在缓存未命中时尝试通过提供的函数加载数据,而getIfPresent方法则只会返回缓存中已存在的数据。例如:

// 获取缓存中已存在的数据
String value1 = cache.getIfPresent("key1");
 
// 缓存未命中时尝试加载数据
String value2 = cache.get("key2", key -> "defaultValue");

⑤缓存驱逐与过期
Caffeine会根据设置的过期策略或驱逐策略自动移除缓存中的数据。例如,当缓存项达到过期时间或缓存容量超过最大限制时,缓存项将被自动移除。

⑥统计与监听
Caffeine提供了缓存统计和监听功能,可以帮助开发者监控缓存的性能和状态。例如,可以通过recordStats方法开启缓存统计功能,并通过Cache.stats()方法获取当前缓存的统计指标。

LoadingCache<String, String> loadingCache = Caffeine.newBuilder()
    .maximumSize(100)
    .recordStats() // 开启缓存统计功能
    .build(key -> "value");
// 获取缓存统计指标
CacheStats stats = loadingCache.stats();
System.out.println("缓存命中率: " + stats.hitRate());

⑦异步缓存
Caffeine还支持异步缓存,可以使用AsyncCache或AsyncLoadingCache来创建异步缓存实例。异步缓存的响应结果是一个CompletableFuture对象,可以在未来某个时间点获取缓存的结果。

⑧其他配置
Caffeine还提供了其他多种配置选项,如设置初始容量、弱引用、软引用等。这些配置可以根据实际需求进行选择和设置。

示例代码
以下是一个完整的示例代码,演示了如何使用Caffeine缓存管理器进行内存缓存的基本操作:

import com.github.benmanes.caffeine.cache.<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值