1.Caffeine是什么
Caffeine是基于Java 8的高性能缓存库,可提供接近最佳的命中率。
缓存类似于ConcurrentMap,但不完全相同。最根本的区别是ConcurrentMap会保留添加到其中的所有元素,直到将其明确删除为止。另一方面,通常将缓存配置为自动移除条目,以限制其内存占用量。在某些情况下,由于LoadCache或AsyncLoadingCache不会自动移除缓存,因此即使移除缓存也可能会很有用。
Caffeine提供灵活的构造来创建具有以下功能组合的缓存:
自动将条目自动加载到缓存中,可以选择异步加载
基于频率和新近度超过最大值时基于大小的过期策略
自上次访问或上次写入以来测得的基于时间的条目到期
发生第一个陈旧的条目请求时,异步刷新
键自动包装在弱引用中
值自动包装在弱引用或软引用中
逐出(或以其他方式删除)条目的通知
写入传播到外部资源
缓存访问统计信息的累积
为了改善集成,扩展模块中提供了JSR-107 JCache和Guava适配器。 JSR-107标准化了基于Java 6的API,以牺牲功能和性能为代价,最大限度地减少了供应商特定的代码。 Guava的Cache是其前身的库,适配器提供了一种简单的迁移策略。
2.SpringBoot中配置Caffeine
spring配置配置缓存,需要配置对应的缓存管理器,然后再需要缓存的地方加上缓存注解
引入需要的包,这里使用的时gradle
compile group: 'org.springframework.boot', name: 'spring-boot-starter-cache', version: '2.4.1'
compile group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: '2.8.8'
配置缓存管理器
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public Caffeine caffeineCache() {
return Caffeine.newBuilder()
.expireAfterWrite(60, TimeUnit.MINUTES);
}
@Bean
public CacheManager cacheManager(Caffeine caffeine) {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
caffeineCacheManager.setCaffeine(caffeine);
return caffeineCacheManager;
}
}
接下来我们创建一张表,然后使用Caffeine缓存
CREATE TABLE `spring_cache` (
`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`cache_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`cache_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of spring_cache
-- ----------------------------
INSERT INTO `spring_cache` VALUES ('1', 'caffeine', 'caffeine');
INSERT INTO `spring_cache` VALUES ('2', 'guava', 'guava');
INSERT INTO `spring_cache` VALUES ('3', 'EhCache', 'EhCache');
INSERT INTO `spring_cache` VALUES ('4', 'Infinispan', 'Infinispan');
使用缓存注解配置,再springboot应用中测试
@Service
@Slf4j
@CacheConfig(cacheNames="caffeine")
public class SpringCacheServiceImpl extends BaseAbstractService<SpringCache,String> implements SpringCacheService<SpringCache,String> {
private static Logger logger = LoggerFactory.getLogger(SpringCacheServiceImpl.class);
@Autowired
SpringCacheRepository springCacheRepository;
@Cacheable(key = "#id")
public SpringCache getCache(String id){
logger.info("get spring caffeine cache,id=[{}]",id);
return springCacheRepository.findById(id).get();
}
@Override
@CacheEvict(key = "#id")
public void removeCache(String id) {
springCacheRepository.deleteById(id);
logger.info("remove spring caffeine cache,id=[{}]",id);
}
@Override
@CachePut( key = "#sc.id")
public void saveCache(SpringCache sc) {
SpringCache newSc=springCacheRepository.saveAndFlush(sc);
logger.info("put spring caffeine cache,id=[{}]",sc.getId());
}
}
注意springboot启动应用中加@EnableCaching。
//实现CommandLineRunner接口
public void run(String... args) throws Exception {
logger.info("spring boot runner");
logger.info("Spring Boot Caffeine Caching Example Configuration");
springCacheService.getCache("1");
springCacheService.getCache("2");
springCacheService.getCache("3");
springCacheService.getCache("4");
Cache cache=cacheManager.getCache("caffeine");
springCacheService.getCache("1");
springCacheService.getCache("2");
}
从控制台可以看出前四条发出sql查询,后面两条没有,证明是读取了缓存
10:20:56.668 [restartedMain] INFO c.zlennon.web.ZlennonWebApplication - Spring Boot Caffeine Caching Example Configuration
10:20:56.785 [restartedMain] INFO c.z.c.s.impl.SpringCacheServiceImpl - get spring caffeine cache,id=[1]
10:20:56.921 [restartedMain] DEBUG org.hibernate.SQL - select springcach0_.id as id1_9_0_, springcach0_.cache_name as cache_na2_9_0_, springcach0_.cache_type as cache_ty3_9_0_ from spring_cache springcach0_ where springcach0_.id=?
10:20:57.016 [restartedMain] INFO c.z.c.s.impl.SpringCacheServiceImpl - get spring caffeine cache,id=[2]
10:20:57.017 [restartedMain] DEBUG org.hibernate.SQL - select springcach0_.id as id1_9_0_, springcach0_.cache_name as cache_na2_9_0_, springcach0_.cache_type as cache_ty3_9_0_ from spring_cache springcach0_ where springcach0_.id=?
10:20:57.021 [restartedMain] INFO c.z.c.s.impl.SpringCacheServiceImpl - get spring caffeine cache,id=[3]
10:20:57.023 [restartedMain] DEBUG org.hibernate.SQL - select springcach0_.id as id1_9_0_, springcach0_.cache_name as cache_na2_9_0_, springcach0_.cache_type as cache_ty3_9_0_ from spring_cache springcach0_ where springcach0_.id=?
10:20:57.027 [restartedMain] INFO c.z.c.s.impl.SpringCacheServiceImpl - get spring caffeine cache,id=[4]
10:20:57.029 [restartedMain] DEBUG org.hibernate.SQL - select springcach0_.id as id1_9_0_, springcach0_.cache_name as cache_na2_9_0_, springcach0_.cache_type as cache_ty3_9_0_ from spring_cache springcach0_ where springcach0_.id=?
同样我们可以查看缓存管理器的缓存
接下来如果我们执行删除和增加操作,会有相应的缓存删除和增加
springCacheService.removeCache("4");
SpringCache sc =new SpringCache();
sc.setId("4");
sc.setCacheName("Infinispan");
sc.setCacheType("Infinispan");
springCacheService.saveCache(sc);
3.原理探索