Caffeine 本地高速缓存工具类

news/2024/11/8 16:36:56/

目录

Caffeine工具类方式

SpringBoot 整合 Caffeine 缓存 (SpringCache模式)

驱逐策略

开发使用


Caffeine是一种高性能的缓存库,是基于Java 8的最佳(最优)缓存框架,性能各方面优于guava。

Caffeine工具类方式

原文链接:https://www.cnblogs.com/wudiffs/p/11585757.html

代码仓库如下:

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

 代码详细示例如下:

public class CaffeineCacheManagerService {private static LoadingCache<String, CacheVO> cache;private static AsyncLoadingCache<String, CacheVO> asyncCache;private static AsyncLoadingCache<String, CacheVO> asyncCache1;private static ExecutorService executorService = new ThreadPoolExecutor(8, 8, 8, TimeUnit.SECONDS, newLinkedBlockingQueue<Runnable>(1204));static {cache = Caffeine.newBuilder()// 初始化缓存长度.initialCapacity(1024 * 10)// 最大长度.maximumSize(1024 * 10)// 更新策略.refreshAfterWrite(10, TimeUnit.SECONDS)// 设置缓存的过期时间.expireAfterWrite(10, TimeUnit.SECONDS).build(new CacheLoader<String, CacheVO>() {// 同步加载@CheckForNull@Overridepublic CacheVO load(@Nonnull String key) throws Exception {return createCacheVO(key);}// getAll将会对缓存中没有值的key分别调用CacheLoader.load方法来构建缓存的值。// 我们可以重写CacheLoader.loadAll方法来提高getAll的效率。@Nonnull@Overridepublic Map<String, CacheVO> loadAll(@Nonnull Iterable<? extends String> keys) throws Exception {return createBatchCacheVOs(keys);}});// 异步加载 同步load写法,最后也会转异步asyncCache = Caffeine.newBuilder().maximumSize(1024 * 10).expireAfterWrite(10, TimeUnit.SECONDS).buildAsync(new CacheLoader<String, CacheVO>() {@CheckForNull@Overridepublic CacheVO load(@Nonnull String key) throws Exception {return createCacheVO(key);}@Nonnull@Overridepublic Map<String, CacheVO> loadAll(@Nonnull Iterable<? extends String> keys) {return createBatchCacheVOs(keys);}});// 异步加载 异步load写法asyncCache1 = Caffeine.newBuilder().maximumSize(1024 * 10).expireAfterWrite(10, TimeUnit.SECONDS).buildAsync(new AsyncCacheLoader<String, CacheVO>() {@Nonnull@Overridepublic CompletableFuture<CacheVO> asyncLoad(@Nonnull String key, @Nonnull Executor executor) {return asyncCreateCacheVO(key, executor);}@Nonnull@Overridepublic CompletableFuture<Map<String, CacheVO>> asyncLoadAll(@Nonnull Iterable<? extends String> keys, @Nonnull Executor executor) {return asyncCreateBatchCacheVOs(keys, executor);}});}public static CompletableFuture<CacheVO> asyncCreateCacheVO(String key, Executor executor) {return CompletableFuture.supplyAsync(() -> createCacheVO(key), executor);}public static CompletableFuture<Map<String, CacheVO>> asyncCreateBatchCacheVOs(Iterable<? extends String> keys, Executor executor) {return CompletableFuture.supplyAsync(() -> createBatchCacheVOs(keys), executor);}public static CacheVO createCacheVO(String key) {return new CacheVO(key);}public static Map<String, CacheVO> createBatchCacheVOs(Iterable<? extends String> keys) {Map<String, CacheVO> result = new HashMap<>();for (String key : keys) {result.put(key, new CacheVO(key));}return result;}public static void main(String[] args) throws Exception {CacheVO cacheVO1 = cache.get("AA");List<String> list = new ArrayList<>();list.add("BB");list.add("CC");Map<String, CacheVO> map = cache.getAll(list);// 如果有缓存则返回;否则运算、缓存、然后返回,整个过程是阻塞的// 即使多个线程同时请求该值也只会调用一次Function方法CacheVO cacheVO2 = cache.get("DD", (k) -> createCacheVO(k));System.out.println(JSON.toJSONString(cacheVO2));// 单个清除cache.invalidate("AA");// 批量清除cache.invalidateAll(list);// 全部清除cache.invalidateAll();// 返回一个CompletableFutureCompletableFuture<CacheVO> future = asyncCache.get("EE");CacheVO asyncCacheVO = future.get();System.out.println(JSON.toJSONString(asyncCacheVO));// 返回一个CompletableFuture<MAP<>>CompletableFuture<Map<String, CacheVO>> allFuture = asyncCache.getAll(list);Map<String, CacheVO> asyncMap = allFuture.get();System.out.println(JSON.toJSONString(asyncMap));CompletableFuture<CacheVO> future1 = asyncCache1.get("FF");CacheVO asyncCacheVO1 = future1.get();System.out.println(JSON.toJSONString(asyncCacheVO1));CompletableFuture<Map<String, CacheVO>> allFuture1 = asyncCache1.getAll(list);Map<String, CacheVO> asyncMap1 = allFuture.get();System.out.println(JSON.toJSONString(asyncMap1));}}

或者使用下发方式实现Caffeine 工具类

支持同步、异步读写缓存实现

import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Caffeine;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;public class CaffeineCacheUtils {private static com.github.benmanes.caffeine.cache.Cache<Object, Object> syncCache;private static AsyncCache<Object, Object> asyncCache;private CaffeineCacheUtils() {}public static void initCache() {syncCache = Caffeine.newBuilder().initialCapacity(100).maximumSize(1000).expireAfterWrite(30, TimeUnit.MINUTES).build();asyncCache = Caffeine.newBuilder().initialCapacity(100).maximumSize(1000).expireAfterWrite(30, TimeUnit.MINUTES).buildAsync();}public static void putSync(Object key, Object value) {syncCache.put(key, value);}public static Object getSync(Object key) {return syncCache.getIfPresent(key);}public static CompletableFuture<Object> getAsync(Object key, Executor executor) {return asyncCache.get(key, k -> CompletableFuture.supplyAsync(() -> fetchDataFromDataSource(k), executor));}public static CompletableFuture<Void> putAsync(Object key, Object value, Executor executor) {return asyncCache.put(key, CompletableFuture.completedFuture(value), executor);}public static void removeSync(Object key) {syncCache.invalidate(key);}public static void clearSync() {syncCache.invalidateAll();}private static Object fetchDataFromDataSource(Object key) {// 模拟从数据源获取数据的操作// 这里可以根据具体业务需求进行实现return null;}
}

 

SpringBoot 整合 Caffeine 缓存 (SpringCache模式)

原文链接:https://blog.csdn.net/Listening_Wind/article/details/110085228

添加依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.6.2</version>
</dependency>

 缓存配置:

 如果使用了多个cahce,比如redis、caffeine等,必须指定某一个CacheManage为@primary

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.assertj.core.util.Lists;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;/*** @Author: Wxy* @Date: 2020/11/7 16:56* @Description*/
@Configuration
@EnableCaching // 开启缓存,否则无效
public class CaffeineConfig {/*** 创建基于Caffeine的Cache Manager** @return*/@Bean@Primarypublic CacheManager caffeineCacheManager() {SimpleCacheManager cacheManager = new SimpleCacheManager();ArrayList<CaffeineCache> caches = Lists.newArrayList();Map<String, Object> map = getCacheType();for (String name : map.keySet()) {caches.add(new CaffeineCache(name, (Cache<Object, Object>) map.get(name)));}cacheManager.setCaches(caches);return cacheManager;}/*** 初始化自定义缓存策略** @return*/private static Map<String, Object> getCacheType() {Map<String, Object> map = new ConcurrentHashMap<>();map.put("name1", Caffeine.newBuilder().recordStats().expireAfterWrite(10, TimeUnit.SECONDS).maximumSize(100).build());map.put("name2", Caffeine.newBuilder().recordStats().expireAfterWrite(50, TimeUnit.SECONDS).maximumSize(50).build());return map;}
}

驱逐策略

基于大小的回收策略有两种方式:基于缓存大小,基于权重,基于时间。
maximumSize : 根据缓存的计数进行驱逐 同一缓存策略 缓存的数据量,以访问先后顺序,以最大100为例,超出100驱逐最晚访问的数据缓存。
maximumWeight : 根据缓存的权重来进行驱逐(权重只是用于确定缓存大小,不会用于决定该缓存是否被驱逐)。
maximumWeight与maximumSize不可以同时使用。

Caffeine提供了三种定时驱逐策略:

expireAfterAccess(long, TimeUnit):在最后一次访问或者写入后开始计时,在指定的时间后过期。假如一直有请求访问该key,那么这个缓存将一直不会过期。
expireAfterWrite(long, TimeUnit): 在最后一次写入缓存后开始计时,在指定的时间后过期。
expireAfter(Expiry): 自定义策略,过期时间由Expiry实现独自计算。
缓存的删除策略使用的是惰性删除和定时删除。这两个删除策略的时间复杂度都是O(1)

开发使用

主要基于Spring缓存注解@Cacheable、@CacheEvict、@CachePut的方式使用

  • @Cacheable :改注解修饰的方法,若不存在缓存,则执行方法并将结果写入缓存;若存在缓存,则不执行方法,直接返回缓存结果。
  • @CachePut :执行方法,更新缓存;该注解下的方法始终会被执行。
  • @CacheEvict :删除缓存
  • @Caching 将多个缓存组合在一个方法上(该注解可以允许一个方法同时设置多个注解)
  • @CacheConfig 在类级别设置一些缓存相关的共同配置(与其它缓存配合使用)

注意 :@Cacheable 默认使用标@primary 注释的CacheManage

/*** 先查缓存,如果查不到,执行方法体并将结果写入缓存,若查到,不执行方法体,直接返回缓存结果* @param id*/
@Cacheable(value = "name1", key = "#id", sync = true)
public void getUser(long id){//TODO 查找数据库
}/*** 更新缓存,每次都会执行方法体* @param user*/
@CachePut(value = "name1", key = "#user.id")
public void saveUser(User user){//todo 保存数据库
}/*** 删除* @param user*/
@CacheEvict(value = "name1",key = "#user.id")
public void delUser(User user){//todo 保存数据库
}

 参考博客:https://www.cnblogs.com/wudiffs/p/11585757.html

(23条消息) SpringBoot 集成 Caffeine(咖啡因)最优秀的本地缓存_springboot caffeine_Listening_Wind的博客-CSDN博客https://blog.csdn.net/Listening_Wind/article/details/110085228


http://www.ppmy.cn/news/87530.html

相关文章

逻辑回归及逻辑回归的评估指标

一、逻辑回归介绍 逻辑回归(Logistic Regression)是机器学习中的一种分类模型&#xff0c;逻辑回归是一种分类算法&#xff0c;虽然名字中带有回归&#xff0c;但是它与回归之间有一定的联系。由于算法的简单和高效&#xff0c;在实际中应用非常广泛。 1.逻辑回归的应用场景 …

hive02

查询练习 练习1 2022-08-07 1,liuyan 2,tangyan 3,jinlian 4,dalang 5,ximenqing ​ 2022-08-08 1,liuyan 2,tangyan 4,dalang 6,wusong ​ -- 创建分区表记录每天用户登陆信息 create table tb_login (uid int,name string ) partitioned by (dt string)row format delimit…

opencv实践-图像去畸变

目录 1.背景2.镜头成像畸变原因3.去畸变方法4. opencv去畸变函数5.代码实现 1.背景 由于相机的镜头并不完全理想&#xff0c;成像时会产生线条扭曲、失真等。对双目图像、鸟瞰图等进行处理时&#xff0c;首先要矫正去畸变。 2.镜头成像畸变原因 相机的镜头前有一块透镜&…

Flutter_环境配置

FlutterSDK 下载FlutterSDK管理工具<SideKick>下载安装<SideKick>下载FlutterSDK设置全局SDK 修改Flutter配置文件获取全局SDK路径 验证配置是否成功验证环境配置 下载FlutterSDK管理工具 下载安装 SideKick下载链接 下载FlutterSDK 打开 SideKick选择需要的SD…

探秘 | 如何分辨内网和外网?

目录 &#x1f4a1; 什么是外网IP、内网IP&#xff1f; &#x1f4a1; 对于自有路由器上网的用户&#xff0c;可以这样理解外网IP、内网IP &#x1f4a1; 几个大家经常会问的问题 什么是外网IP、内网IP&#xff1f;很多用户都有一个疑惑&#xff0c;如果不使用路由器拨号上网…

五大网络IO模型

网络IO模型 1. IO是什么&#xff1f; I/O&#xff08;英语&#xff1a;Input/Output&#xff09;&#xff0c;即输入&#xff0f;输出&#xff0c;通常指数据在存储器&#xff08;内部和外部&#xff09;或其他周边设备之间的输入和输出&#xff0c;是信息处理系统&#xff0…

android 12.0控制Camera开启功能实现

1.概述 在12.0的产品开发中,需要增加系统属性, 通过系统属性值来控制camera开关来实现是否可用camera的目的,这就需要通过相关管理类来控制相机是否可用打开来实现 2.控制Camera开启功能实现的核心代码 frameworks/base/core/java/android/hardware/camera2/CameraManager…

mysql时间字段属性:datetime、date、timestamp 作用及区别

MySQL字段属性&#xff1a; datetime: 用于存储日期和时间&#xff0c;格式为YYYY-MM-DD HH:MM:SS&#xff0c;范围从’1000-01-01 00:00:00’到’9999-12-31 23:59:59’。 date: 用于存储日期&#xff0c;格式为YYYY-MM-DD&#xff0c;范围从’1000-01-01’到’9999-12-31’…