🧑 博主简介:CSDN博客专家 ,历代文学网 (PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可微信小程序搜索"历代文学 ")总架构师,
15年
工作经验,精通Java编程
,高并发设计
,Springboot和微服务
,熟悉Linux
,ESXI虚拟化
以及云原生Docker和K8s
,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。
技术合作 请加本人wx(注明来自csdn ):foreast_sea


Caffeine 三种过期策略详解
在 Caffeine
中,cache.policy()
提供的三种过期策略接口(expireAfterWrite
、expireAfterAccess
、expireVariably
)分别对应不同的缓存过期机制。以下是它们的核心区别和适用场景:
1. expireAfterWrite
(固定写入过期)
java
Policy.FixedExpiration<String, String> policy =
cache.policy().expireAfterWrite().orElse(null);
特点:
-
基于写入时间:从条目创建或最后一次更新开始计时
-
固定持续时间:所有条目使用相同的过期时间
-
配置方式 :
javaCaffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES)
适用场景:
- 数据变更频率低
- 需要保证数据新鲜度(如配置信息)
- 简单易用的通用方案
示例:
java
// 设置所有条目写入后10分钟过期
policy.setExpiresAfter(10, TimeUnit.MINUTES);
// 获取当前过期时间
long duration = policy.getExpiresAfter(TimeUnit.MINUTES); // 返回10
2. expireAfterAccess
(固定访问过期)
java
Policy.FixedExpiration<String, String> policy =
cache.policy().expireAfterAccess().orElse(null);
特点:
-
基于访问时间:每次读取或写入都会重置计时器
-
固定持续时间:所有条目使用相同的空闲时间
-
配置方式 :
javaCaffeine.newBuilder() .expireAfterAccess(30, TimeUnit.MINUTES)
适用场景:
- 频繁访问的热点数据
- 读多写少的场景(如用户会话)
- 需要保留活跃数据的缓存
示例:
java
// 设置所有条目30分钟未访问则过期
policy.setExpiresAfter(30, TimeUnit.MINUTES);
// 获取当前过期时间
long duration = policy.getExpiresAfter(TimeUnit.MINUTES); // 返回30
3. expireVariably
(可变过期)
java
Policy.VarExpiration<String, String> policy =
cache.policy().expireVariably().orElse(null);
特点:
-
完全动态:可为每个条目设置不同过期时间
-
细粒度控制:支持运行时修改任意条目的过期时间
-
配置方式 :
javaCaffeine.newBuilder() .expireAfter(new Expiry<String, String>() { // 自定义实现 })
适用场景:
- 不同条目需要不同过期时间
- 动态调整过期策略(如促销商品短期缓存)
- 高级缓存管理需求
示例:
java
// 设置testKey 5秒后过期
policy.put("testKey", "value", 5, TimeUnit.SECONDS);
// 设置importantKey 24小时过期
policy.put("importantKey", "value", 24, TimeUnit.HOURS);
// 修改testKey的过期时间
policy.setExpiresAfter("testKey", 10, TimeUnit.SECONDS);
核心区别对比表
特性 | expireAfterWrite | expireAfterAccess | expireVariably |
---|---|---|---|
时间基准 | 写入时间 | 访问时间 | 任意时间 |
时间单位 | 固定 | 固定 | 可变 |
重置机制 | 仅写入重置 | 读取/写入均重置 | 手动控制 |
配置方式 | 全局统一 | 全局统一 | 按条目设置 |
内存开销 | 低 | 低 | 较高(+24字节/条目) |
使用复杂度 | ★☆☆☆☆ | ★☆☆☆☆ | ★★★★☆ |
适用场景 | 数据变更敏感 | 热点数据保留 | 精细化控制 |
组合策略实现
虽然 Caffeine 本身不直接支持同时配置多种策略,但可通过 Expiry
接口模拟组合策略:
java
Caffeine.newBuilder()
.expireAfter(new Expiry<String, String>() {
// 默认策略:写入后30分钟过期
public long expireAfterCreate(String key, String value, long currentTime) {
return TimeUnit.MINUTES.toNanos(30);
}
// 特殊key:访问后1小时过期
public long expireAfterRead(String key, String value, long currentTime, long currentDuration) {
if ("hotKey".equals(key)) {
return TimeUnit.HOURS.toNanos(1);
}
return currentDuration;
}
// 更新时重置为写入过期
public long expireAfterUpdate(String key, String value, long currentTime, long currentDuration) {
return TimeUnit.MINUTES.toNanos(30);
}
})
生产环境建议
-
优先选择固定策略:
java// 80%场景适用 .expireAfterWrite(30, TimeUnit.MINUTES)
-
动态策略注意事项:
- 启用调度器:
.scheduler(Scheduler.systemScheduler())
- 监控内存:可变策略增加约24字节/条目开销
- 避免频繁修改:批量操作更高效
- 启用调度器:
-
过期策略选择指南:
场景 推荐策略 示例配置 配置信息 expireAfterWrite 5-10分钟 用户会话 expireAfterAccess 30分钟 热点数据 expireAfterAccess 1小时 短期活动 expireVariably 按需设置 金融数据 expireAfterWrite 1分钟 -
监控与调优:
java// 获取过期条目统计 long expiredCount = cache.stats().evictionCount(); // 检查策略是否生效 if (cache.policy().expireAfterWrite().isPresent()) { // 固定写入策略已启用 }
通过理解这三种策略的核心区别,我们可以根据业务场景选择最合适的缓存过期管理方案。