caffeine 使用、本地缓存选择

项目需要支持缓存,要求轻量级,个人选择相比其他缓存库(如 Ehcache, Guava Cache, Redis, Memcached 等)具有几个显著的优势,尤其是在内存效率、性能和灵活性方面

caffeine优势:

1.极致的性能和低内存开销。
2.丰富且灵活的 缓存过期和刷新策略。
3.高效的并发性能和线程安全。
4.简单易用的集成方式,尤其与 Spring 集成非常方便。

下面是个人引入的坐标;

<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.9.1</version>
</dependency>

CacheConfig

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager() {
            protected Cache<Object, Object> createNativeCache(String name) {
                return Caffeine.newBuilder()
                        .expireAfterAccess(10, TimeUnit.MINUTES)// 设置缓存数据在30分钟没有访问就过期
                        .refreshAfterWrite(6, TimeUnit.MINUTES)// 每15分钟强制更新一次缓存
                        //.expireAfterWrite(10, TimeUnit.MINUTES)//缓存项在被写入后,10分钟后自动过期
                        .maximumSize(100)// 设置缓存的最大大小
                        .build(new CacheLoader<Object, Object>() {
                            @Override
                            public Object load(Object key) throws Exception {
                                // 这里可以加载数据,例如调用数据库或者其他服务
                                return null; // 返回加载的数据
                            }
                        });
            }
        };
        //设置缓存名称,有需要可以放开注解
        //cacheManager.setCacheNames(Arrays.asList("userCache", "sensorCache"));
        return cacheManager;
    }
}
@Cacheable 注解启用缓存。
@CachePut 强制更新缓存
@CacheEvict 清除缓存。

注解放入缓存、注解查询

//注解存入
    @CachePut(value = "sensorCache", key = "'SENSOR' + #sensorInfo.mac")
    @Override
    public SensorInfo saveSensorInfo_annotate(SensorInfo sensorInfo) {
        return sensorInfo;
    }

    // 使用 @Cacheable 注解,自动从缓存中获取数据
    @Cacheable(value = "sensorCache", key = "'SENSOR' + #terminalCode")
    @Override
    public SensorInfo querySensorInfo_annotate(String terminalCode) {
        // 如果缓存中没有数据,下面加查询方法
        return null;
    }

手动放入

#更新版
//手动添加
    @Override
    public void saveSensorInfo(SensorInfo sensorInfo) {
        cacheManager.getCache("sensorCache").put("SENSOR" + sensorInfo.getMac(), sensorInfo);
    }

    //手动查询
    @Override
    public SensorInfo querySensorInfo(String terminalCode) {
        Cache<String, SensorInfo> cache = (Cache<String, SensorInfo>) cacheManager.getCache("sensorCache").getNativeCache();
        // 使用 Caffeine 缓存的 getIfPresent 方法获取缓存
        SensorInfo sensorInfo = cache.getIfPresent("SENSOR" + terminalCode);

        if (sensorInfo != null) {
            return sensorInfo;
        } else {
            return null;
        }
    }

#原版

String cacheKey = companyCode + "-" + deptId;
// 从缓存中获取数据
List<SuitBorrowCountConfigDTO> cachedResult = (List<SuitBorrowCountConfigDTO>) cacheManager.getCache("borrowConfigCache").get(cacheKey);
if (cachedResult != null) {
   return cachedResult;  // 如果缓存中存在数据,直接返回
 }
// 将结果放入缓存
cacheManager.getCache("borrowConfigCache").put(cacheKey, dtos);

查看缓存项

    @Autowired
    private CacheManager cacheManager;

    public void printJCache() {
        Iterable<String> cacheNames = cacheManager.getCacheNames();
        for (String cacheName : cacheNames) {
            Cache cache = cacheManager.getCache(cacheName);
            System.out.println("Cache Name: " + cacheName);
            // 打印缓存内容
            System.out.println("Cache Contents: " + cache);
        }
    }

查看缓存项---对象值

public class CaffeineCacheController {
    @Autowired
    private CacheManager cacheManager;

    @GetMapping
    public void printJCache() {
        Iterable<String> cacheNames = cacheManager.getCacheNames();
        for (String cacheName : cacheNames) {
            Cache cache = cacheManager.getCache(cacheName);
            System.out.println("Cache Name: " + cacheName);
            // 获取缓存中的某个对象,假设你知道 key
            String cacheKey = "SENSOR04EEE810090B"; // 根据需要的 key 修改

            // 获取缓存内容
            SensorInfo sensorInfo = (SensorInfo) cache.get(cacheKey).get();

            if (sensorInfo != null) {
                // 如果缓存中有数据,打印出其详细信息
                System.out.println("Cache Contents for " + cacheKey + ": " + sensorInfo);
            } else {
                System.out.println("Cache does not contain data for key: " + cacheKey);
            }
        }
    }
}

### Caffeine Hybrid本地缓存使用教程与配置方法 Caffeine 是一种高性能的 Java 缓存库,广泛用于构建高效的本地缓存解决方案。它支持多种缓存策略,包括 LRU(最近最少使用)、LFU(最不常用)以及基于时间的淘汰机制。对于混合型(Hybrid)缓存的需求,可以通过灵活配置来满足不同场景下的性能需求。 以下是关于如何实现和配置 Caffeine 的 Hybrid 本地缓存的具体说明: #### 1. 添加依赖项 为了在项目中集成 Caffeine,需先将其作为 Maven 或 Gradle 依赖引入。 ##### Maven 配置 ```xml <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>3.0.5</version> <!-- 版本号可能随时间更新 --> </dependency> ``` ##### Gradle 配置 ```gradle implementation 'com.github.ben-manes.caffeine:caffeine:3.0.5' ``` --- #### 2. 基础配置示例 以下是一个简单的 Caffeine 缓存初始化代码片段,展示了基本的功能设置。 ```java import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; public class CacheExample { public static void main(String[] args) { // 创建一个带有最大容量和过期策略的缓存实例 Cache<String, String> cache = Caffeine.newBuilder() .maximumSize(10_000) // 设置最大条目数 .expireAfterWrite(10, TimeUnit.MINUTES) // 写入后失效时间 .build(); // 插入键值对 cache.put("key", "value"); // 获取缓存中的值 System.out.println(cache.getIfPresent("key")); // 输出 "value" } } ``` 此基础配置可以扩展为更复杂的混合模式,具体取决于业务需求。 --- #### 3. 实现 Hybrid 缓存逻辑 Hybrid 缓存通常指结合两种或更多种缓存策略以适应不同的访问模式。例如,在某些场景下需要兼顾高频随机访问和批量扫描操作[^4]。通过组合多个淘汰策略,可以达到更好的效果。 下面展示了一个自定义淘汰策略的例子: ```java Cache<String, Object> hybridCache = Caffeine.newBuilder() .initialCapacity(100) // 初始容量 .maximumSize(10_000) // 最大容量 .expireAfterAccess(5, TimeUnit.MINUTES) // 访问后失效时间 .expireAfterWrite(10, TimeUnit.MINUTES) // 写入后失效时间 .recordStats() // 启用统计功能以便监控 .removalListener((key, value, cause) -> { // 移除监听器,可用于记录日志或其他清理工作 System.out.println("Removed key=" + key + ", reason=" + cause); }) .build(); ``` 在此基础上,还可以进一步定制化行为,比如动态调整缓存大小或者根据特定条件触发刷新动作。 --- #### 4. 结合堆内外存储方案 如果希望利用堆外内存减少 GC 负担,则可以选择其他工具配合 Caffeine 使用,如 OffHeapStore 或 Ehcache 等[^1]。不过需要注意的是,这类实现会增加开发复杂度并影响跨平台兼容性。 另外,考虑到 Aerospike 这样的 NoSQL 数据库提供了高度优化过的闪存读写能力[^2],也可以考虑将部分热数据迁移到此类外部服务当中去处理。 --- #### 性能调优建议 - **合理设定缓存边界**:依据实际负载情况调整 `maximumSize` 和各种超时参数。 - **启用异步加载**:当面对高并发请求时,推荐采用异步填充的方式降低主线程压力。 - **定期分析状态报告**:借助 `.recordStats()` 方法收集运行期间的各项指标,进而发现潜在瓶颈所在位置。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值