关于Caffeine Cache
Google Guava Cache是一种非常优秀本地缓存解决方案,提供了基于容量,时间和引用的缓存回收方式。基于容量的方式内部实现采用LRU算法,基于引用回收很好的利用了Java虚拟机的垃圾回收机制。其中的缓存构造器CacheBuilder采用构建者模式提供了设置好各种参数的缓存对象,缓存核心类LocalCache里面的内部类Segment与jdk1.7及以前的ConcurrentHashMap非常相似,都继承于ReetrantLock,还有六个队列,以实现丰富的本地缓存方案。 通俗的讲,Guva是google开源的一个公共java库,类似于Apache Commons,它提供了集合,反射,缓存,科学计算,xml,io等一些工具类库。cache只是其中的一个模块。使用Guva cache能够方便快速的构建本地缓存。
Caffeine是使用Java8对Guava缓存的重写版本,在Spring Boot 2.0中将取代Guava。如果出现Caffeine,CaffeineCacheManager将会自动配置。
1.1.1 为什么要用本地缓存
相对于IO操作 速度快,效率高 相对于Redis Redis是一种优秀的分布式缓存实现,受限于网卡等原因,远水救不了近火
-- 下面来看看,各种本地缓存框架的读写对比
引入依赖:
<!-- springboot 缓存--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!-- caffeine 依赖--> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency>
在启动类上加入注解:
Caffeine在springboot中集成非常简单,可以通过配置文件来设置
spring: cache: cache-names: outLimit,notOutLimit caffeine: spec: initialCapacity=50,maximumSize=500,expireAfterWrite=5s,refreshAfterWrite=7s type: caffeine
或者使用注解的形式注入
package cn.aiaudit.model.config; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.TimeUnit; /** *配置caffeine作为模型的本地缓存 */ @Configuration public class CacheConfig { @Bean public Cache caffeineCache() { return Caffeine.newBuilder() // 设置最后一次写入或访问后经过固定时间过期 .expireAfterWrite(60, TimeUnit.SECONDS) // 初始的缓存空间大小 .initialCapacity(100) // 缓存的最大条数 .maximumSize(500) .build(); } }
下面介绍获取和存储缓存数据,可以基于注解的形式,也可以使用手动的形式
1.
@Autowired Cache<String, Object> caffeineCache;
caffeineCache.put(String.valueOf(po.getId()), vo); // 先从缓存读取 caffeineCache.getIfPresent(id); SqlInsertIntoProgressVO vo = (SqlInsertIntoProgressVO)caffeineCache.asMap().get(id);
2.
@Slf4j @Service @CacheConfig(cacheNames = "caffeineCacheManager") public class UserInfoServiceImpl implements UserInfoService { /** * 模拟数据库存储数据 */ private HashMap<Integer, UserInfo> userInfoMap = new HashMap<>(); @Override @CachePut(key = "#userInfo.id") public void addUserInfo(UserInfo userInfo) { log.info("create"); userInfoMap.put(userInfo.getId(), userInfo); } @Override @Cacheable(key = "#id") public UserInfo getByName(Integer id) { log.info("get"); return userInfoMap.get(id); } @Override @CachePut(key = "#userInfo.id") public UserInfo updateUserInfo(UserInfo userInfo) { log.info("update"); if (!userInfoMap.containsKey(userInfo.getId())) { return null; } // 取旧的值 UserInfo oldUserInfo = userInfoMap.get(userInfo.getId()); // 替换内容 if (!StringUtils.isEmpty(oldUserInfo.getAge())) { oldUserInfo.setAge(userInfo.getAge()); } if (!StringUtils.isEmpty(oldUserInfo.getName())) { oldUserInfo.setName(userInfo.getName()); } if (!StringUtils.isEmpty(oldUserInfo.getSex())) { oldUserInfo.setSex(userInfo.getSex()); } // 将新的对象存储,更新旧对象信息 userInfoMap.put(oldUserInfo.getId(), oldUserInfo); // 返回新对象信息 return oldUserInfo; } @Override @CacheEvict(key = "#id") public void deleteById(Integer id) { log.info("delete"); userInfoMap.remove(id); }
-- 以上