存储简介:最开始使用的存储结构是文件形式(如:操作系统),但这时就存在一个问题,比如:查一个大的文件的时候,就是需要全量IO(在全部文件堆中找到你需要的文件),受磁盘寻址(毫秒)和带宽的影响会很慢,所以应运而生是的数据库(如mysql),数据库通过索引和分治(一堆数据分成m块-建表)降低了复杂度,但数据库在数据量过大、高并发等场景出现时也会出现瓶颈,这时有两种解决方案,一是换高并发处理、负载均衡和分布式数据库(如:HANA-成本高),二是放缓存(纳秒)里,还有一种折中的方法就是将数据库做全量数据,1/N的热点数据放缓存,自此就产生了内存型数据库(如:redis、memcache),这样缓存就是在内存中存储的数据备份,当数据没有发生本质改变的时候,我们就不让数据的查询去数据库进行操作,而去内存中取数据,来提高效率。
提到缓存就不得不提到大名鼎鼎的JSR107
JSR是Java Specification Requests的缩写,意思是Java 规范提案。
2012年10月26日JSR规范委员会发布了JSR 107(JCache API)的首个早期草案。自该JSR启动以来,已经过去近12年时间,因此该规范颇为Java社区所诟病,但由于对缓存需求越来越多,因此专家组加快了这一进度。
JCache规范定义了一种对Java对象临时在内存中进行缓存的方法,包括对象的创建、共享访问、假脱机(spooling)、失效、各JVM的一致性等,可被用于缓存JSP内最经常读取的数据,如产品目录和价格列表。利用JCACHE,多数查询的反应时间会因为有缓存的数据而加快(内部测试表明反应时间大约快15倍)。
Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry。
示意图:
Spring从3.1开始定义了org.springframework.cache.Cache 和org.springframework.cache.CacheManager接口来统一不同的缓存技术; 并支持使用JCache(JSR-107)注解简化我们开发。
1.、确定方法需要被缓存以及他们的缓存策略
2、从缓存中读取之前缓存存储的数据
摘自链接:https://blog.csdn.net/huanghanqian/article/details/103129358
StackOverFlow上有一个问题https://stackoverflow.com/questions/37780249/spring-boot-cachable-cache-size,提问者使用了Spring Boot的@EnableCaching和@Cacheable注解,想自行设置cacheable缓存的默认最大容量。
public interface VendorRepository extends Repository{ @Cacheable("vendorByUsername") Vendor getVendorByUsername(String username); @CacheEvict(value = {"vendorByUsername", "vendor", "vendors"}, allEntries = true) Vendor save(Vendor vendor); @Cacheable("vendor") Vendor findOne(Long id); @Cacheable("vendors") List findAll(); }
其实这位提问者有一个误解。Spring的Cacheable注解,不代表Cacheable就是一个具体的缓存实例。这个注解仅仅是一个抽象层,为缓存的各个实现规范定义。至于缓存的默认大小、最大容量……这些都取决于你使用的具体缓存实现。
Spring的Cache抽象不会对cache中低层次的细节语义进行处理(比如cache大小、cache驱除(eviction)、cache到期(expiration)等),因为这些低层次的信息在不同cache实现间差异很大。比如,不少缓存是分布式的,它们在一致性、冗余性和控制延迟的实现策略上具有很大的差别,因此,如果说cache接口也需要对一致性进行抽象的话,就无法兼容那些非分布式缓存了。具体的话,可以看看《Spring Reference Guide》https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache-specific-config 中对于这一部分的总结:
8.7. How can I Set the TTL/TTI/Eviction(驱逐) policy/XXX feature?
直接通过你的cache provider来实现。The cache abstraction是一种抽象,而不是一种实现。你使用的解决方案可能会包含不同的数据策略和拓扑规则,而其它解决方案可能会不支持这些特性。
Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支持使用JCache(JSR-107)注解简化我们开发;
Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;
Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache ,ConcurrentMapCache等;
当然你也可以使用其它组件提供的实现,比如Guava和Caffeine(来自goole):
可以通过下图观测到,在下面缓存组件中 Caffeine 性能是其中最好的。
按 Caffeine Github 文档描述,Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件。具体为什么可以参考此文:https://blog.csdn.net/qq_33330687/article/details/88857030
每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
使用Spring缓存抽象时我们需要关注以下两点;
1、确定方法需要被缓存以及他们的缓存策略;
2、从缓存中读取之前缓存存储的数据
一、本地缓存方法一:springbootcache+Caffeine
本地缓存适合在单服务器上使用,不适合分布式,因为没有了网络的时间消耗,表现上可能会更好
实现可以参考此链接:https://zhuanlan.zhihu.com/p/109226599
又可以叫分布式缓存,讲缓存单独作为一个服务器,多有分布式服务器都去这台服务器上进行数据存取
实现可参照:https://blog.csdn.net/weixin_38750084/article/details/88526746
或者此文:https://www.jianshu.com/p/8b026187dc62