• redis 03 springboot 缓存


    Something before start

    主要解决两种缓存场景
    1、实时更新的缓存 即一般的查询时候,把记录写进缓存。
    2、不需要实时的缓存 即不需要很准确的数据//比如用户数量什么的。对于这种情况,需要注意缓存雪崩的问题。这里是使用双重检测锁来解决这个问题的。

    缓存雪崩:数据到期,大量请求涌入到数据库

    依赖

            <!--redis-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    

    配置文件

    连接redis

    有三种形式连接。另外注意配置redis的配置文件

    # 关闭保护模式
    protected-mode no
    # 把这个注释掉,开启外地连接
    #bind 
    

    单机

    spring.redis.host=127.0.0.1
    spring.redis.port=6379
    #spring.redis.password=
    

    哨兵模式集群

    # 这个mymaster 可以直接在sentinel.conf里找到,可以更换成自己喜欢的hhhh
    spring.redis.sentinel.master=mymaster
    # 这里展示的是多种写法,多个哨兵
    spring.redis.sentinel.nodes=locathost:26379,127.0.0.1:26380,locathost:26381
    spring.redis.sentinel.password=
    

    cluster集群

    # 连接redis集群 //cluster模式
    spring.redis.cluster.nodes=127.0.0.1:7006,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005
    #spring.redis.password=
    

    指定springboot缓存形式

    # 指定cache类型
    spring.cache.type=redis
    # 缓存区域名称 //随便取都行 同时可以多缓存空间
    spring.cache.cache-names=realTimeCache
    

    实体类序列化

    很简单,只要实现java的序列化接口就行Serializable
    序列化简单理解就是把一个对象转化成字符流

    public class Employee implements Serializable {
        private Integer id;
        private String name;
        private int age;
        //省略其他乱七八糟的东西
    

    注解方式

    怎么确保缓存准确性

    每次更新数据的时候就清理所有的缓存,在查询的时候将数据时写入缓存。因为redis本身性能很高,所以不用担心性能啥的。

    启动类开启缓存

    @EnableCaching 开启缓存

    @EnableCaching
    @EnableTransactionManagement
    @SpringBootApplication
    public class RedisdemoApplication {
    

    更新数据 清理缓存

    @CacheEvict: 放在更新(增删改)数据的方法上

    1. value是前面配置的缓存区域名称。
    2. 当注解参数加上allEntries为true时,意思是说这个清除缓存是清除当前value值空间下的所有缓存数据。
        //更新数据 则 更新清理缓存
        @CacheEvict(value = "realTimeCache", allEntries = true)
        @PostMapping("regist")
        public void registHandle(Employee employee) {
            employeeService.regist(employee);
        }
    

    查询数据 更新缓存

    @Cacheable:放在查询的方法上

        //value:缓存空间 key:键
        @Cacheable(value = "realTimeCache", key = "'emloyee_'+#id")
        @GetMapping("find")
        public Employee findHandle(int id) {
            return employeeService.findEmployeeById(id);
        }
    

    API方式

    什么是双重检测锁

    第一次检测:进入方法,如果有值则返回,如果取出来为空则开启同步阻塞其他线程请求。
    第二次检测:进入同步线程之后,再次检测是否有值,有则返回,无则将请求送到数据库。
    为什么需要第二次检测:第一取不到值的线程进入同步的时候,可能会有其他请求跑进来。第一个线程更新完之后,其他的线程就不许要重新更新,所以需要第二次检测

    实现代码

        //使用双重检测锁 解决 热点缓存问题
        @GetMapping("count")
        public Integer countHandle() {
            //获取redis操作对象 和count绑定 count即key
            BoundValueOperations<Object, Object> ops = redisTemplate.boundValueOps("count");
    
            //从缓存中获得数据
            Object count = ops.get();
    
            if (count==null){
                //因为上锁之后阻塞了 会有新的请求到这里,所以需要上锁后重新检测保证后面来的不会击穿
                //因为是单例 所以可以用this
                synchronized (this){
                    count = ops.get();
                    if (count==null){
                        count = employeeService.findEmployeeCount();
                        ops.set(count,10, TimeUnit.SECONDS);//存入 存活10秒
                    }
                }
            }
            return (Integer)count;
        }
    

    自动生成key

    一样是使用codeConfig方式。
    然后就可以把注解里的那个key删掉了
    注意这里的para只适合一个参数的情况//其实写一个循环就完事了
    暂时懒得写解释,感性理解一下就好/

    @Configuration
    public class RedisCacheConfig extends CachingConfigurerSupport {
        //自动生成key结构:类名_方法名_参数
        @Override
        public KeyGenerator keyGenerator() {
            return (target,method,params)->{
                String className = target.getClass().getName();
                String methodName =  method.getName();
                return className+"-"+methodName+"-"+params[0].toString();
            };
        }
    }
    
  • 相关阅读:
    Python的包管理工具Pip
    C语言移位运算符
    malloc函数具体解释
    HDU
    Java中Scanner的使用方法
    DOS call 中的%cd%,当前文件夹演示
    没有找到MSVCR100.dll解决方法
    什么是响应式表格(响应式表格和普通表格的区别)
    Redis和Memcache和MongoDB简介及区别分析(整理)
    GIT将本地项目上传到Github(两种简单、方便的方法)
  • 原文地址:https://www.cnblogs.com/sariseBlog/p/14942464.html
Copyright © 2020-2023  润新知