• Springboot整合缓存


    一、为什么使用缓存

    一个应用主要瓶颈在于数据库的IO,大家都知道内存的速度是远远快于硬盘的速度(即使固态硬盘与内存也无法比拟)。

    应用之中经常会遇到某些数据变化的可能性很小。假如我们使用传统的方式每次都通过接口与数据库打交道去请求获得,每次既消耗了内存资源、网络资源、数据库资源、CPU资源,又导致大量的时间耗费在数据库查询,及远程方法调用上,从而导致程序性能的恶化。

    这种场景就是需要使用缓存来解决这类问题。我们把数据缓存在内存之中,以后每次获取直接内存之中获得;使得程序获得极大的性能提升。

    二、Springcache

    1、SpringCache介绍

    SpringCache相当于一个抽象接口,在其底层可以切换各种Cache的实现,当缓存数据时,只需要注入SpringCache对应的注解,即可实现缓存的功能,大大的提高了缓存的效率,这就是Spring自带缓存SpringCache的使用原理

    Springcache默认的缓存实现是simple(内存级),当然可以更换成其他实现,常见的有如下

    EhCache:此缓存框架一直伴随着Spring,Hibernate,Mybatis等等。在SpringBoot出来之前都已经广泛的使用来做为一级缓存

    Guava: Google出品的框架,也支持缓存

    Redis:在我们日常开发之中经常使用的;并且被大众广泛接受的速度极快的缓存

    memcached:是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。

    Spring缓存的接口:

    org.springframework.cache.Cache ;

    org.springframework.cache.CacheManager

    这两个接口都在context中,一个是用来提供缓存,一个是用来提供管理缓存。

    CacheManager是Spring提供的各种缓存技术抽象接口,

    Cache接口包含缓存的各种操作(增加、删除、获得缓存,我们一般不会直接和此接口打交道)。

    Spring支持的CacheManager实现如下图: 

    使用缓存需要引入的依赖是

    1. org.springframework.boot
    2. spring-boot-starter-cache

    2、注解

    2.1、配置注解

    EnableCaching

    标注于SpringBoot应用启动类上,添加此注解表示开启Spring Cache缓存;移除表示关闭缓存。如果在全局配置文件中添加如下配置,即使在启动类上标注EnableCaching注解,Spring Cache缓存然后是关闭状态。

    1. spring:
    2. cache:
    3. type: none

    如果应用中自定义独立于Spring容器的缓存,则不受此配置影响。 

    CacheConfig

    标注于类上,更具体的说是标注于业务服务类上。统一配置如下参数信息:

    参数含义使用说明
    cacheManager缓存管理器缺省指首要的CacheManager
    cacheNames缓存名
    keyGeneratorkey值生成器

    在类上统一进行配置,类下的方法自动继承相应的配置。

    2.2、缓存注解

    Cacheable

    添加缓存的核心注解,分两种情况:一是对应key值未有缓存数据,先执行方法,然后根据condition和unless条件决定是否添加缓存;二是对应key值已有缓存,不执行方法体,直接返回数据。

    1. /**
    2. *value:自定义缓存空间名
    3. *key:缓存的key
    4. */
    5. @Cacheable(value = "cacheSpace",key ="#id" )
    6. public List list(String id){
    7. return Arrays.asList("1","2","3");
    8. }

    基础参数

    参数含义使用说明
    cacheManager缓存管理器缺省指首要的CacheManager
    cacheNames缓存名
    keyGeneratorkey值生成器
    keykey值

    参数keyGeneratorkey是互斥的,当key存在时keyGenerator配置自动失效。 

    高级参数 

    参数含义默认值使用说明
    condition缓存条件指示满足条件方执行缓存操作,一般使用参数作为条件
    unless否定缓存当条件为 true ,方法的返回值不会被缓存
    sync同步状态false表示将方法执行结果以何种方式存入缓存

    CachePut

    更新缓存注解。不管对应key值是否有缓存数据,都执行。

    基础参数

    参数含义使用说明
    cacheManager缓存管理器缺省指首要的CacheManager
    cacheNames缓存名
    keyGeneratorkey值生成器
    keykey值

    高级参数

    参数含义使用说明
    condition缓存条件指示满足条件方执行缓存操作,一般使用参数作为条件
    unless否定缓存当条件为 true ,方法的返回值不会被缓存

    CacheEvict

    主动清除缓存注解。

    基础参数

    参数含义使用说明
    cacheManager缓存管理器缺省指首要的CacheManager
    cacheNames缓存名
    keyGeneratorkey值生成器
    keykey值

    高级参数

    参数含义默认值使用说明
    condition缓存条件指示满足条件方执行缓存操作,一般使用参数作为条件
    allEntries所有缓存false表示是否清空当前CacheName对应的所有缓存
    beforeInvocation调用前false表示是否在方法调用前清空缓存

     3、实现方式

    默认cache接口的实现simple(内存级),直接使用上面的注解即可,没有什么需要配置的,可以自己选择合适的缓存,

    3.1、Ehcache作为缓存

    可以在spring-boot-dependencies发现有Echcache依赖,所以我们只需引入依赖,不需要版本

    需要导入的依赖

    1. <dependency>
    2. <groupId>net.sf.ehcache</groupId>
    3. <artifactId>ehcache</artifactId>
    4. </dependency>

    配置

    1. spring:
    2. cache:
    3. type: EHCACHE

    还需要一个Ehcache的配置文件ehcache.xml

    1. "1.0" encoding="UTF-8"?>
    2. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
    4. updateCheck="false">
    5. <diskStore path="java.io.tmpdir/Tmp_EhCache"/>
    6. <defaultCache
    7. eternal="false"
    8. maxElementsInMemory="10000"
    9. overflowToDisk="false"
    10. diskPersistent="false"
    11. timeToIdleSeconds="1800"
    12. timeToLiveSeconds="259200"
    13. memoryStoreEvictionPolicy="LRU"/>
    14. <cache
    15. name="cloud_user"
    16. eternal="false"
    17. maxElementsInMemory="5000"
    18. overflowToDisk="false"
    19. diskPersistent="false"
    20. timeToIdleSeconds="1800"
    21. timeToLiveSeconds="1800"
    22. memoryStoreEvictionPolicy="LRU"/>
    23. ehcache>

     使用方式还是用上面的注解

    3.2、redis作为缓存

    引入依赖

    1. org.springframework.boot
    2. spring-boot-starter-cache
    3. org.springframework.boot
    4. spring-boot-starter-data-redis

    注意:这里是把redis作为cache实现进行整合,即springcache整合redis,并不是springboot整合redis

    配置

    1. spring:
    2. cache:
    3. type: EHCACHE
    4. redis:
    5. #是否缓存空值
    6. cache-null-values: true
    7. #是否使用前缀
    8. use-key-prefix: true
    9. #前缀
    10. key-prefix: test
    11. #缓存时间
    12. time-to-live: 10s
    13. redis:
    14. host: localhost
    15. port: 6379

     使用方式还是用上面的注解

    3.3、memcached作为缓存

    下载安装memcached

    地址Windows 下安装 Memcached | 菜鸟教程

    下载后解压,cmd执行exe文件

    memcached.exe -d install

    安装如果出现failed to install servise or service is already installed,此时使用管理员身份打开cmd执行上面安装命令即可

    然后启动和停止服务

    memcached.exe -d start
    memcached.exe -d stop

    boot对memcached没有提供相应的整合,需要使用编码方式实现客户端管理,memcached客户端有一下三个

    memcached client for java:最早期客户端 稳定可靠 用户群广(类似redis中的jedis)

    SpyMemcached :效率更高

    Xmemcached:并发处理更好

    这里演示三个最好的Xmemcached使用

    1. <dependency>
    2. <groupId>com.googlecode.xmemcached</groupId>
    3. <artifactId>xmemcached</artifactId>
    4. <version>2.4.7</version>
    5. </dependency>

     配置bean

    1. @Configuration
    2. public class XMemcachedConfig {
    3. @Bean
    4. public MemcachedClient memcachedClient() throws IOException {
    5. XMemcachedClientBuilder xMemcachedClientBuilder = new XMemcachedClientBuilder("localhost:11211");
    6. //自己根据需要设置其他参数
    7. xMemcachedClientBuilder.setConnectionPoolSize(20);
    8. MemcachedClient memcachedClient = xMemcachedClientBuilder.build();
    9. return memcachedClient;
    10. }
    11. }

    测试

    1. @RequestMapping("mSet")
    2. @ResponseBody
    3. public String mSet() throws InterruptedException, TimeoutException, MemcachedException {
    4. memcachedClient.set("token",0,Arrays.asList("1","2","3"));
    5. return "ok";
    6. }
    7. @RequestMapping("mGet")
    8. @ResponseBody
    9. public String mGet() throws InterruptedException, TimeoutException, MemcachedException {
    10. return memcachedClient.get("token").toString();
    11. }

    详情教程

    Memcached 教程 | 菜鸟教程

    3.4、jetcache作为缓存

    上面几种缓存技术有以下几点特点

    1、配置方式多样性,有xml中配置的、有yml配置文件的、有代码中写的,比较散乱

    2、缓存有本地方案和远程方案(redis)

    阿里提供的jetcache设定了本地缓存和远程缓存的多级缓存解决方案,用来替代spring-cache的

    • 本地缓存

            LinkedHashMap

            Caffeine

    • 远程缓存

            Redis(本文选择远程方案)

            Tair

    使用jetcache之后就需要引入spring-boot-starter-cache,加入jetcache依赖

    1. com.alicp.jetcache
    2. jetcache-starter-redis
    3. 2.6.2

    注意:boot整合jetcache只需引入上面依赖即可,如果不是boot整合,需要引入的是

    jetcache anno和jetcache core两个依赖

    jetcache远程&本地缓存方案

    配置

    1. jetcache:
    2. #area是否进入拼接到缓存的key
    3. areaInCacheName: false
    4. #远程配置 默认default即可,远程方案使用redis ,其中poolConfig必须配置
    5. remote:
    6. default:
    7. type: redis
    8. host: localhost
    9. port: 6379
    10. keyConvertor: fastjson
    11. valueEncode: java
    12. valueDecode: java
    13. poolConfig:
    14. maxTotal: 50
    15. minIdle: 5
    16. maxIdle: 20
    17. test:
    18. type: redis
    19. host: localhost
    20. port: 6379
    21. keyConvertor: fastjson
    22. valueEncode: java
    23. valueDecode: java
    24. poolConfig:
    25. maxTotal: 50
    26. minIdle: 5
    27. maxIdle: 20
    28. #本地缓存配置
    29. local:
    30. default:
    31. type: linkedhashmap
    32. keyConvertor: fastjson
    33. valueEncode: java
    34. valueDecode: java

    启动类开启缓存

    1. @SpringBootApplication
    2. //jetache缓存开启
    3. @EnableCreateCacheAnnotation
    4. public class TestApplication {
    5. public static void main(String[] args) {
    6. SpringApplication.run(TestApplication.class, args);
    7. }
    8. }
    1. /**
    2. *定义缓存对象
    3. * area:和配置文件配置的要对应,如果配置文件remote只有default 这个area可以省略
    4. * name:空间配置 最好使用下划线或者其他符号和缓存的key隔开
    5. * expire:过期时间 默认单位秒
    6. * timuit:可选配置,默认单位秒
    7. * cacheType:当前缓存类型,只在本地缓存还是远程,
    8. * 取值CacheType.BOTH,CacheType.REMOTE CacheType.LOCAL三个取值 默认REMOTE
    9. */
    10. @CreateCache(area = "test",name = "testCache_",expire = 3600,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.REMOTE)
    11. private Cache jetCache;
    12. public void jetCachePut(){
    13. //redis中的key是:test_testCache_token
    14. jetCache.put("token","111111111111111111");
    15. }
    16. public String jetCacheGet(){
    17. return jetCache.get("token");
    18. }

    jetcache方法缓存

    需要在启动类开启方法缓存注解

    1. @SpringBootApplication
    2. //jetache缓存开启
    3. @EnableCreateCacheAnnotation
    4. //开启方法缓存
    5. @EnableMethodCache(basePackages = {"com.test"})
    6. public class TestApplication {
    7. public static void main(String[] args) {
    8. SpringApplication.run(TestApplication.class, args);
    9. }
    10. }

    使用如下

    1. /**
    2. * 方法缓存注解(使用方法缓存时放入缓存的实体类要实现序列化接口)
    3. */
    4. @Cached(name = "user_",key="#id",expire = 3600,cacheType = CacheType.BOTH)
    5. public User getById(Integer id){
    6. return userDao.getById(id);
    7. }
    8. /**
    9. * 更新数据时同时把缓存中的数据更新
    10. * vaule表示新的数据
    11. */
    12. @CacheUpdate(name = "user_",key="#user.id",value = "#user")
    13. public void updateUser(User user){
    14. userDao.update(user);
    15. }
    16. /**
    17. * 删除数据时候同时删除缓存中的数据
    18. * vaule表示新的数据
    19. */
    20. @CacheInvalidate(name = "user_",key = "#id")
    21. public void delUser(Integer id){
    22. userDao.delUser(id);
    23. }

    如果同一套系统部署到两台机器,a机器改了数据但是b没有收到通知,此时可以使用cache提供的一个定义刷新缓存的注解

    1. @Cached(name = "user_",key="#id",expire = 3600,cacheType = CacheType.BOTH)
    2. @CacheRefresh(refresh = 5)
    3. public User getById(Integer id){
    4. return userDao.getById(id);
    5. }

    查看jetcache缓存报告报表

    只需增加一个配置

    1. jetcache:
    2. #查看缓存报告:1min后
    3. statIntervalMinutes: 1

    控制台定时打印缓存命中相关 

     3.5、j2cache

    j2cache是一个缓存整合框架,使各种缓存配合使用,自身不提供缓存

    使用参考视频

    实用开发篇-116-j2cache相关配置_哔哩哔哩_bilibili

  • 相关阅读:
    每天一个数据分析题(三百九十二)- 多元线性回归
    2299: 计算并输出学生成绩
    在WSL2中安装多个Ubuntu实例
    loadrunner脚本--添加事务
    robotframework RequestsLibrary Post On Session关键字 body为json的问题
    深入理解CyclicBarrie
    水果叠叠乐
    MySQL内连接和外连接及七种SQL JOINS的实现
    从物理转AI、战数据库,95后程序员的职业选择
    Nacos win10 安装配置教程
  • 原文地址:https://blog.csdn.net/qq_34491508/article/details/126790207