springboot整合redis缓存一些知识点

前言

最近在做智能家居平台,考虑到家居的控制需要快速的响应于是打算使用redis缓存。一方面减少数据库压力另一方面又能提高响应速度。项目中使用的技术栈基本上都是大家熟悉的springboot全家桶,在springboot2.x以后操作redis的客户端推荐使用lettuce(生菜)取代jedis。

jedis的劣势主要在于直连redis,又无法做到弹性收缩。

一、配置文件

application.yml文件中的内容

spring:
  application:
    name: simple-lettuce
  cache:
    type: redis
    redis:
      # 缓存超时时间ms
      time-to-live: 60000
      # 是否缓存空值
      cache-null-values: true
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    # 连接超时时间(毫秒)
    timeout: 60000
    # Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
    database: 1
    # spring2.x redis client 采用了lettuce(生菜),放弃使用jedis
    lettuce:
      # 关闭超时时间
      shutdown-timeout: 30000
      pool:
        # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-active: 30
        # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-wait: -1
        # 连接池中的最大空闲连接 默认 8
        max-idle: 8
        # 连接池中的最小空闲连接 默认 0
        min-idle: 0

说明:

  • spring.cache.type: redis

已经表明使用项目采用redis做为缓存方式。

  • spring.cache.redis.cache-null-values: true

表示是否缓存空值,一般情况下是允许的。因为这涉及到缓存的三大问题:缓存穿透、缓存雪崩、缓存击穿。

如果设置false即不允许缓存空值,这样会导致很多请求数据库没有的数据时,不会缓存到redis导致每次都会请求到数据库。这种情况即:缓存穿透。

具体想初步了解这些概念可以参考文章:缓存三大问题及解决方案!

二、config配置类

@Configuration
@EnableCaching
public class RedisTemplateConfig extends CachingConfigurerSupport {

    private static Map<String, RedisCacheConfiguration> cacheMap = Maps.newHashMap();

    @Bean(name = "stringRedisTemplate")
    @ConditionalOnMissingBean(name = "stringRedisTemplate") //表示:如果容器已经有redisTemplate bean就不再注入
    public StringRedisTemplate stringRedisTemplate(LettuceConnectionFactory redisConnectionFactory) {return new StringRedisTemplate(redisConnectionFactory);
    }

    @Bean(name = "redisTemplate")
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        System.out.println("RedisTemplateConfig.RedisTemplate");
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // key的序列化采用StringRedisSerializer
        template.setKeySerializer(keySerializer());
        template.setHashKeySerializer(keySerializer());
        // value值的序列化采用fastJsonRedisSerializer
        template.setValueSerializer(valueSerializer()); //使用fastjson序列化
        template.setHashValueSerializer(valueSerializer()); //使用fastjson序列化
        template.setConnectionFactory(lettuceConnectionFactory);
        return template;
    }

    /**
     * 添加自定义缓存异常处理
     * 当缓存读写异常时,忽略异常
     * 参考:https://blog.csdn.net/sz85850597/article/details/89301331
     */
    @Override
    public CacheErrorHandler errorHandler() {
        return new IgnoreCacheErrorHandler();
    }

    @SuppressWarnings("Duplicates")
    @Bean
    @Primary//当有多个管理器的时候,必须使用该注解在一个管理器上注释:表示该管理器为默认的管理器
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        // 默认配置
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(keyPair())
                .serializeValuesWith(valuePair())
                .entryTtl(Duration.ofSeconds(DEFAULT_TTL_SECS)) //设置过期时间
                .disableCachingNullValues();

        // 其它配置
        for(MyCaches cache : MyCaches.values()) {
            cacheMap.put(cache.name(),
                    RedisCacheConfiguration.defaultCacheConfig()
                            .serializeKeysWith(keyPair())
                            .serializeValuesWith(valuePair())
                            .entryTtl(cache.getTtl())
                            // .disableCachingNullValues() // 表示不允许缓存空值
                            .disableKeyPrefix() // 不使用默认前缀
                    // .prefixKeysWith("mytest") // 添加自定义前缀
            );
        }

        /** 遍历MyCaches添加缓存配置*/
        RedisCacheManager cacheManager = RedisCacheManager.builder(
                RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory)
        )
                .cacheDefaults(defaultCacheConfig)
                .withInitialCacheConfigurations(cacheMap)
                .transactionAware()
                .build();

        ParserConfig.getGlobalInstance().addAccept("mypackage.db.entity.");
        return cacheManager;
    }

    /**
     * key序列化方式
     * @return
     */
    private RedisSerializationContext.SerializationPair<String> keyPair() {
        RedisSerializationContext.SerializationPair<String> keyPair =
                RedisSerializationContext.SerializationPair.fromSerializer(keySerializer());
        return keyPair;
    }

    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }

    /**
     * value序列化方式
     * @return
     */
    private RedisSerializationContext.SerializationPair<Object> valuePair() {
        RedisSerializationContext.SerializationPair<Object> valuePair =
                RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer());
        return valuePair;
    }

    /**
     * 使用fastjson序列化
     * @return
     */
    private RedisSerializer<Object> valueSerializer() {
        MyFastJsonRedisSerializer<Object> fastJsonRedisSerializer = new MyFastJsonRedisSerializer<>(Object.class);
        return fastJsonRedisSerializer;
    }

    @Getter
    private enum MyCaches {
        defaultCache(Duration.ofDays(1)),
        MyCaches(Duration.ofMinutes(10));

        MyCaches(Duration ttl) {
            this.ttl = ttl;
        }
        /** 失效时间 */
        private Duration ttl = Duration.ofHours(1);
    }
}

 说明

1. 类上的注解@EnableCaching

表明开启缓存功能。

2. extends CachingConfigurerSupport

这个类就很丰富了,其实如果没有什么特别操作也可以不用继承这个类。

这个类可以支持动态选择缓存方式,比如项目中不止一种缓存方案,有可能有ehcache那么可以自定义在什么情况下使用redis使用情况下使用ehcache。还有一些有关异常的处理。我也不是很懂具体可以参考:

springboot(25)自定义缓存读写机制CachingConfigurerSupport

3. StringRedisTemplate和RedisTemplate的使用

(1)两者的主要差别是:如果你只想缓存简单的字符串选择StringRedisTemplate是一个明智的举措。如果想使用redis缓存一些对象数据肯定是要选择RedisTemplate。

(2)RedisTemplate需要注意一点就是要怎么选择序列化工具。默认使用jdk的序列化缓存数据后即value值是无法直接阅读的而存的二进制数据。

通常我们会选择jackson或者fastjson来序列化对象,把对象转换成json格式。两者序列化对象后都会在头部加上一个对象类路径如:@type com.mypackage.entity.User。这个也算是一种安全策略。

比如使用fastjosn就会在cacheManager中指定序列化对象的包所在位置白名单:ParserConfig.getGlobalInstance().addAccept("mypackage.db.entity.");

fastjson官方说明:https://github.com/alibaba/fastjson/wiki/enable_autotype

(3)还有需要注意如果value是string类型。RedisTemplate会在字符串外围再加一对双引号,如""abc""。如果使用RedisTemplate读取则能得到abc,但是我在项目使用Jedis读取就成了"abc"这就导致这些字符串无法被反序列化。

(4)StringRedisTemplate和RedisTemplate两者数据是相互隔离的,如果使用StringRedisTemplate存入的数据使用RedisTemplate是无法读取、删除的。

三、缓存注解使用

@Cacheable 使用在查询方法上

@CachePut 使用在更新、保存方法上

@CacheEvict 使用在删除方法上

需要注意的是@Cacheable、@CachePut方法一定要有返回被缓存对象。因为注解使用的AOP切面如果没有返回值表示缓存对象为空值。

@CacheConfig注解在类上,可以选择使用哪个缓存、缓存管理器、Key生成器

好了以上就是最近在项目中的一些知识点总结,如果以后使用缓存有新的体会我会同步更新的。

原文地址:https://www.cnblogs.com/backnow/p/11824061.html

时间: 2024-10-07 22:24:49

springboot整合redis缓存一些知识点的相关文章

SpringBoot 整合 Redis缓存

在我们的日常项目开发过程中缓存是无处不在的,因为它可以极大的提高系统的访问速度,关于缓存的框架也种类繁多,今天主要介绍的是使用现在非常流行的NoSQL数据库(Redis)来实现我们的缓存需求. SpringBoot整合Redis是非常方便快捷的,我用的是Mybatis,这里就不说Springboot整合Mybatis了网上有很多,同样非常简单. 下面进入正题: 原文地址:https://www.cnblogs.com/yueguanguanyun/p/9756058.html

SpringBoot整合redis缓存(一)

准备工作 1.Linux系统 2.安装redis(也可以安装docker,然后再docker中装redis,本文章就直接用Linux安装redis做演示) redis下载地址:http://download.redis.io/releases/redis-4.0.14.tar.gz 修改redis,开启远程访问 找到redis中的redis.conf文件并编辑(在安装路径中找到) vim ./redis.conf 1.找到bind 127.0.0.1并注释掉 默认127.0.0.1只能本地访问,

springboot整合redis缓存

https://www.jianshu.com/p/a8694d97caaa https://blog.csdn.net/tianyaleixiaowu/article/details/70314277 https://www.cnblogs.com/yuxiang1/p/9282952.html 原文地址:https://www.cnblogs.com/wwmiert/p/11126948.html

九、springboot整合redis二之缓冲配置

1.创建Cache配置类 @Configuration @EnableCaching public class RedisCacheConfig extends CachingConfigurerSupport { @Value("${redis.cache.expiration}") private Long expiration; /** * * 管理缓存 */ @Bean public CacheManager cacheManager(RedisTemplate<Obje

SpringBoot整合Redis并完成工具类

SpringBoot整合Redis的资料很多,但是我只需要整合完成后,可以操作Redis就可以了,所以不需要配合缓存相关的注解使用(如@Cacheable),而且我的系统框架用的日志是log4j,不是SpringBoot默认的Logback.通过查询资料我完成了Redis整合,并写了Redis操作工具类.特意在此记录一下,分享给大家,也方便以后查阅. 1.SpringBoot版本如下 <parent> <groupId>org.springframework.boot</gr

超简单!!!SpringBoot整合Redis

1.导入Pom.xml依赖 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.ap

Spring Boot 学习----SpringBoot整合Redis

SpringBoot整合Redis 说明:由于使用的是window系统,所以本文中使用的redis是再Docker中运行的. 至于如何启动redis这里不再说明,需要的请自行百度. 配置pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </depend

三:Springboot整合Redis

一:springboot整合redis redis版本:3.0.0 运行环境:linux 1.安装redis 1.1安装gcc yum install gcc-c++ 1.2解压redis.3.0.0.tar.gz压缩包 tar -zxvf redis-3.0.0.tar.gz 1.3进入解压后的目录进行编译 cd redis-3.0.0 make 1.4将redis安装到指定目录 make PREFIX=/usr/local/redis install 1.5启动redis ./redis-s

springboot整合redis实现缓存

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>1.5.2.RELEASE</version> </dependency> spring: redis: ##默认redis客户端连接为0 可修改 database: 0