• SpringCache


    为什么使用缓存 ?

    因为我们的热点数据也就是经常用到的数据,如果不加redis缓存我们用户经常访问这些数据,就会经常访问mysql,但是MySQL数据是存在硬盘中的就会走IO,这时候我们可以将这些数据放到缓存中,如果缓存有就去缓存拿如果缓存没有就去MySQL,这样可以提高效率

     缓存穿透

    缓存和数据库中都没有的数据,那么这时候数据来访问redis缓存,当查数据时发现reids缓存没有去查询MySQL,导致每次查这个数据都去数据库查询,这样就像redis缓存被穿透了,MySQL大量过来请求导致宕机。

    解决方案:   

    1 使用限流   

    2 创建一个空的,key:1   value:null   这样访问第一次发现数据库没有就保持这个key的value设置为null    但是这个设置的过期时间短一点,防止MySQL已经存在该数据了还是返回的null

    3 使用布隆过滤器存储可能访问的key,当不存在这个key时就会把这个请求过滤

    缓存击穿

    当MySQL有这个数据但是redis没有这个数据,如果多个用户都来访问这个热点数据,导致大量用户并发读取缓存发现没有这个数据,同时去MySQL中读取,导致的数据库压力增大

    解决方案:
    1  热值热点数据永不过期     由定时任务定时更新缓存

    2 添加互斥锁   同一时间只能有一个用户来访问,但是会导致变成单线程

    缓存雪崩

    大量的热点数据在同一时间过期,导致数据访问时发现缓存中key已经过期了,热点数据的访问很多都去MySQL中访问了,导致了MySQL请求量增大

    解决方式:
    1      过期时间打散,将热点数据的过期时间不弄在一起

    2      缓存分布式       将数据均匀分布到不同的缓存数据库中

    3      热点数据不过期      热点的数据不过期这样就防止了同一时间热点数据过期

    4    添加互斥锁    该方式和缓存击穿一样,按 key 维度加锁,对于同一个 key,只允许一个线程去计算,其他线程原地阻塞等待第一个线程的计算结果,然后直接走缓存即可。

    spring-cache概述及核心配置

    Spring Cache就是一个这个框架。它利用了AOP,实现了基于注解的缓存功能,并且进行了合理的抽象,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解,就能实现缓存功能了

    使用步骤

    添加依赖

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-cacheartifactId>
    4. dependency>

    添加配置

    1. package com.itheima.restkeeper.config;
    2. import org.springframework.beans.factory.annotation.Qualifier;
    3. import org.springframework.cache.CacheManager;
    4. import org.springframework.cache.annotation.EnableCaching;
    5. import org.springframework.context.annotation.Bean;
    6. import org.springframework.context.annotation.Configuration;
    7. import org.springframework.data.redis.cache.RedisCacheConfiguration;
    8. import org.springframework.data.redis.cache.RedisCacheManager;
    9. import org.springframework.data.redis.connection.RedisConnectionFactory;
    10. import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
    11. import org.springframework.data.redis.serializer.RedisSerializationContext;
    12. import org.springframework.data.redis.serializer.RedisSerializer;
    13. import org.springframework.data.redis.serializer.StringRedisSerializer;
    14. import java.time.Duration;
    15. /**
    16. * @ClassName RedisCacheConfig.java
    17. * @Description redis配置
    18. */
    19. @Configuration
    20. //开启caching的支持
    21. @EnableCaching
    22. public class RedisCacheConfig {
    23. /**
    24. * 申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)
    25. * 根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,
    26. * 将数据添加到缓存之中或者从缓存中移除某个值
    27. * @return
    28. */
    29. @Bean
    30. public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    31. //对key的序列化操作:String
    32. RedisSerializer redisSerializer = new StringRedisSerializer();
    33. //对value的序列化操作:json
    34. GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer =
    35. new GenericJackson2JsonRedisSerializer();
    36. //配置config,指定超时时间记得key val 序列化处理
    37. RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
    38. //指定全局超时时间【60S】
    39. .entryTtl(Duration.ofSeconds(60))
    40. //配置key的序列化方式
    41. .serializeKeysWith(RedisSerializationContext
    42. .SerializationPair
    43. .fromSerializer(redisSerializer))
    44. //配置value的序列化方式
    45. .serializeValuesWith(RedisSerializationContext
    46. .SerializationPair
    47. .fromSerializer(genericJackson2JsonRedisSerializer))
    48. //关闭空值的存储
    49. .disableCachingNullValues();
    50. //使用建造者进行初始化
    51. return RedisCacheManager.builder(redisConnectionFactory)
    52. .cacheDefaults(config)
    53. .build();
    54. }
    55. }

    配置类

    1. #spring相关配置
    2. spring:
    3. main:
    4. allow-bean-definition-overriding: true
    5. redis:
    6. redisson:
    7. config: classpath:singleServerConfig.yaml
    8. #redis配置信息
    9. host: 192.168.112.77
    10. port: 6379
    11. password: pass

    优雅使用spring-cache

    选择Face的理由:

    1、face是dubbo服务生

    2、service的功能过于细腻,并且关联甚广

    3、control层功能过于粗狂,不易缓存的维护

     注解

    对于缓存声明,spring的缓存提供了一组java注解:

    • @Cacheable:触发缓存写入,如果缓存中没有:查询数据库,存储缓存,返回结果。如果缓存中有:直接返回缓存结果

    • @CacheEvict:触发缓存清除。

    • @CachePut:更新缓存(不会影响到方法的运行)。

    • @Caching:重新组合要应用于方法的多个缓存操作

    2.1、@Cacheable注解

    ==如果缓存中没有:查询数据库,存储缓存,返回结果,如果缓存中有:直接返回结果==

    作用:可以用来进行缓存的写入,将结果存储在缓存中,以便于在后续调用的时候可以直接返回缓存中的值,而不必再执行实际的方法。 最简单的使用方式,注解名称=缓存名称,使用例子如下:

    2.2、@CacheEvict注解

    @CacheEvict:删除缓存的注解,这对删除旧的数据和无用的数据是非常有用的。这里还多了一个参数(allEntries),设置allEntries=true时,可以对整个条目进行批量删除

    2.3、@CachePut注解

    @CachePut:当需要更新缓存而不干扰方法的运行时 ,可以使用该注解。也就是说,始终执行该方法,并将结果放入缓存

    2.4、@Caching注释

    在使用缓存的时候,有可能会同时进行更新和删除,会出现同时使用多个注解的情况.而@Caching可以实现

    //添加user缓存的同时,移除userPage的缓存
    @Caching(put =@CachePut(value = "user",key ="#userVo.id"),
            evict = @CacheEvict(value = "userPage",allEntries = true))

    ==使用的规则:==

    ==1、项目启动时候需要增加哪些数据的热加载,以方便查询时候直接使用【@Cacheable】==

    ==2、增删改更新缓存【@CachePut,@CacheEvict】,查使用缓存【@Cacheable】==

    ==3、复杂场景中需要执行多条命令时候使用【@Caching】=

  • 相关阅读:
    栈的运行算法
    MySQL数据库管理
    云呐|动环监控设备维护与常见故障处理
    华硕电脑自带壁纸位置
    react的table合并行时,出现border-bottom重复问题
    elasticsearch
    [附源码]计算机毕业设计汽车租赁管理系统Springboot程序
    解锁机器人技术的钥匙—《应用机器人学:运动学、动力学与控制技术》
    Mac电脑怎么使用NTFS磁盘管理器 NTFS磁盘详细使用教程
    干谷净重694.27公斤 滦南国稻种芯-517功能性苦瓜稻北方旱作
  • 原文地址:https://blog.csdn.net/hnhroot/article/details/126297184