SpringBoot 集成 Caffeine Cache 实践。
简介
Caffeine 是一个高性能的Java本地缓存库,采用 W-TinyLFU 算法(结合 LRU 和 LFU 优势),显著提升缓存命中率,尤其在复杂访问模式下表现优异。
接入
添加依赖
Java 8
1 2 3 4 5 6 7 8 9
| <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.9.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
|
Java 11 及以上
1 2 3 4 5 6 7 8 9
| <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>3.1.8</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
|
配置 Caffeine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import com.github.benmanes.caffeine.cache.Caffeine; import org.springframework.cache.CacheManager; import org.springframework.cache.caffeine.CaffeineCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.cache.annotation.EnableCaching;
import java.util.concurrent.TimeUnit;
@EnableCaching @Configuration public class LocalCacheConfiguration {
@Bean @Primary public CacheManager defaultCacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); cacheManager.setCaffeine(Caffeine.newBuilder() .expireAfterWrite(1, TimeUnit.HOURS) .maximumSize(1024)); return cacheManager; }
@Bean public CacheManager ephemeralCacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); cacheManager.setCaffeine(Caffeine.newBuilder() .expireAfterWrite(5, java.util.concurrent.TimeUnit.SECONDS) .maximumSize(1024)); return cacheManager; } }
|
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Cacheable(value = "msg:sub", key = "#p0 + #p1 + #p2.getType()", cacheManager = "ephemeralCacheManager") public boolean checkUserSubscribe(Long tenantId, String productKey, SubscribeMsgTypeEnum msgTypeEnum) { if (loggerConfig.isLogEnable(OPEN_DEVICE_MSG_LOG)) { log.info("checkUserSubscribe cache not matched, tenantId:{}, productKey:{}, type:{}", tenantId, productKey, msgTypeEnum.getType()); } List<String> subscribedTypeList = tenantCustomConfigComponent.getCachedSubscribeMsgTypeList(tenantId, productKey); if (subscribedTypeList == null) { return false; } return subscribedTypeList.contains(msgTypeEnum.getType()); }
@Cacheable(value = "prd:tnt", key = "#p0", cacheManager = "defaultCacheManager", unless = "#result == null") public Long getProductTenantId(String productKey) { if (loggerConfig.isLogEnable(OPEN_DEVICE_MSG_LOG)) { log.info("getProductTenantId cache not matched, productKey:{}", productKey); } Long tenantId = productComponent.getCachedProductTenantId(productKey); return tenantId; }
|
注意点
@Cacheable 注解是依赖于 AOP 实现的, 所以必须跨类使用,同时方法必须是 public 的
@Cacheable 中的 key 是SpEL 表达式,注意语法,如果拿不到参数名,可以使用 p0 按序号获取参数标识
@Cacheable 支持特定情况下缓存或不缓存,参见 unless、condition 属性
- 不要忘记配置
@EnableCaching 启用缓存支持
- Java 8 支持的版本是 2.X
- 可以使用
Cache cache = cacheManager.getCache("prd:tnt"); 手动操作缓存