Springboot本地缓存和redis缓存

存储简介:最开始使用的存储结构是文件形式(如:操作系统),但这时就存在一个问题,比如:查一个大的文件的时候,就是需要全量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倍)。

JSR107

Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry。

示意图

  • CachingProvider定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可 以在运行期访问多个CachingProvider。
  • CacheManager定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache 存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
  •  Cache是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个 CacheManager所拥有。
  •  Entry是一个存储在Cache中的key-value对。
  •  Expiry 每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期 的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。
  • Springboot本地缓存和redis缓存_第1张图片

2.Spring缓存抽象

Spring从3.1开始定义了org.springframework.cache.Cache 和org.springframework.cache.CacheManager接口来统一不同的缓存技术; 并支持使用JCache(JSR-107)注解简化我们开发。

  • Cache接口为缓存的组件规范定义,包含缓存的各种操作集合。
  • Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache。
  • 每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否 已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法 并缓存结果后返回给用户。下次调用直接从缓存中获取。
  •  使用Spring缓存抽象时我们需要关注以下两点:

            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

Springboot本地缓存和redis缓存_第2张图片

  • 每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。

  • 使用Spring缓存抽象时我们需要关注以下两点;

    1、确定方法需要被缓存以及他们的缓存策略;

    2、从缓存中读取之前缓存存储的数据

本地缓存

一、本地缓存方法一:springbootcache+Caffeine

本地缓存适合在单服务器上使用,不适合分布式,因为没有了网络的时间消耗,表现上可能会更好

实现可以参考此链接:https://zhuanlan.zhihu.com/p/109226599

redis缓存(远程缓存)

又可以叫分布式缓存,讲缓存单独作为一个服务器,多有分布式服务器都去这台服务器上进行数据存取

实现可参照:https://blog.csdn.net/weixin_38750084/article/details/88526746

或者此文:https://www.jianshu.com/p/8b026187dc62

 

 

 


 

你可能感兴趣的:(记录)