Redis和Spring Cache

Redis

Redis的安装

这里附上一篇博客来进行在windows的安装,因此不再过多的赘述:Windows下安装和配置Redis_redis下载安装配置windows-CSDN博客

Redis 的特点和功能

  • 性能优秀,数据在内存中,读写速度非常快,支持并发 10W QPS(每秒查询量)。
  • 单进程单线程,是线程安全的,采用 IO 多路复用机制。
  • 丰富的数据类型,支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。
  • 支持数据持久化。
  • 可以将内存中数据保存在磁盘中,重启时加载。
  • 主从复制,哨兵,高可用。
  • 可以用作分布式锁。
  • 可以作为消息中间件使用,支持发布订阅

Redis在springboot上面的配置

application.yml:

spring:
  data:
    redis:
      database: 0
      host: localhost
      port: 6379
      password:
      timeout: 3000
      lettuce:
        pool:
          min-idle: 0
          max-active: 8
          max-idle: 8
          max-wait: -1ms
      connect-timeout: 30000ms

RedisConfig:

package org.example.jedistest.config;

import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.nio.charset.StandardCharsets;
import java.time.Duration;


/**
 * redis配置类
 *
 * @author zq
 */

@Configuration
@EnableCaching
public class RedisConfig {

    // 倘若 spring.redis.host 不存在,则会默认为127.0.0.1.
    @Value("${spring.data.redis.host:}")
    private String hostName;

    @Value("${spring.data.redis.port:}")
    private int port;

    @Value("${spring.data.redis.password:}")
    private String password;

    @Value("${spring.data.redis.timeout:}")
    private int timeout;

    @Value("${spring.data.redis.lettuce.pool.max-idle:}")
    private int maxIdle;

    @Value("${spring.data.redis.lettuce.pool.min-idle:}")
    private int minIdle;

    @Value("${spring.data.redis.lettuce.pool.max-active:}")
    private int maxActive;

    @Value("${spring.data.redis.database:}")
    private int databaseId;

    @Bean
    public LettuceConnectionFactory lettuceConnectionFactory() {

        RedisConfiguration redisConfiguration = new RedisStandaloneConfiguration(
                hostName, port
        );

        // 设置选用的数据库号码
        ((RedisStandaloneConfiguration) redisConfiguration).setDatabase(databaseId);

        // 设置 redis 数据库密码
        ((RedisStandaloneConfiguration) redisConfiguration).setPassword(password);

        // 连接池配置
        GenericObjectPoolConfig<Object> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMaxIdle(maxIdle);
        poolConfig.setMinIdle(minIdle);
        poolConfig.setMaxTotal(maxActive);

        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder
                = LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(timeout));

        LettucePoolingClientConfiguration lettucePoolingClientConfiguration = builder.build();

        builder.poolConfig(poolConfig);

        // 根据配置和客户端配置创建连接
        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfiguration, lettucePoolingClientConfiguration);
        return factory;
    }

    /**
     * springboot2.x 使用LettuceConnectionFactory 代替 RedisConnectionFactory
     * application.yml配置基本信息后,springboot2.x  RedisAutoConfiguration能够自动装配
     * LettuceConnectionFactory 和 RedisConnectionFactory 及其 RedisTemplate
     *
     * @param
     * @return
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(
            LettuceConnectionFactory lettuceConnectionFactory
    ) {

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);

        // 使用 FastJsonRedisSerializer 来序列化和反序列化redis 的 value的值
        FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
        ParserConfig.getGlobalInstance().addAccept("com.muzz");
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setCharset(StandardCharsets.UTF_8);
        serializer.setFastJsonConfig(fastJsonConfig);

        // key 的 String 序列化采用 StringRedisSerializer
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);

        // value 的值序列化采用 fastJsonRedisSerializer
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashValueSerializer(serializer);

        redisTemplate.afterPropertiesSet();

        System.out.println(redisTemplate.getDefaultSerializer());

        return redisTemplate;
    }

    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {

        // 使用 FastJsonRedisSerializer 来序列化和反序列化redis 的 value的值
        FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
        ParserConfig.getGlobalInstance().addAccept("com.muzz");
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setCharset(StandardCharsets.UTF_8);
        serializer.setFastJsonConfig(fastJsonConfig);
        return serializer;
    }
}

pom.xml:

这下面的配置是我单独添加的,Redis因为在项目生成的时候勾选就行了就没放进去

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--连接池依赖-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.8.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>

基本结构类型 

 基本操作

SpringBoot项目实战 - SpringBoot使用RedisTemplate_springboot redistemplate-CSDN博客

Spring Cache

几大注释

  1. 标注 @EnableCaching到启动类或者配置类上,开启缓存功能
  2. 使用 SpringCache缓存注解标注到业务方法上,常用的注解如下:

对于缓存声明,Spring的缓存抽象提供了一组Java注解:

  • @Cacheable:触发缓存填充的操作。
  • @CacheEvict: 触发缓存删除的操作。
  • @CachePut:在不干扰方法执行的情况下更新缓存。
  • @Caching:重新组合多个缓存操作以应用于一个方法,即使用该注解内部可以组合使用其他注解(@CacheEvict、@CachePut、@Cacheable)
  • @CacheConfig:在类级别共享一些常见的缓存相关设置。

引入依赖

<!-- 引入 SpringCache-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

配置文件

spring:
  cache:
    type: redis 				  #指定使用redis作为缓存
    redis:
#      key-prefix:                # 配置所有缓存key的前缀,不配置,默认格式为  "缓存自定义的value::SimpleKey []"
      time-to-live: 3600000        # 配置 ttl 缓存过期时间,单位毫秒,这里设置了3600秒,即1个钟失效
      cache-null-values: true     # 是否缓存 Null 值,默认为 true,默认解决“缓存穿透”问题。
      use-key-prefix: true        # 是否使用key前缀,默认为 true

@Cacheable

    //1、Cacheable代表当前方法的结果需要缓存,如果缓存中有,方法不用调用。如果缓存中没有会调用方法,最后将方法的结果放入缓存
	//2、每一个需要缓存的数据,都要指定要放到哪个名字的缓存分区。【缓存的分区(建议按照业务类型分,方便统一删除)】
	@Cacheable(value = {"category"}) 
    @Override
    public List<CategoryEntity> getLevel1Categorys() {
        // 查db操作 ,略;
    }

测试发现, SpringCahe默认行为如下:

  1. 如果缓存中有数据,该方法不用被调用;
  2. key默认自动生成: 缓存的名字::SimpLeKey[](自主生成的key值);
  3. 缓存的 value 的值。默认使用 “jdk序列化机制 org.springframework.data.redis.serializer.JdkSerializationRedisSerializer”,将序列化后的数据存到 redis ;
  4. 默认 ttl 时间 -1,永久;

参数

  • value:必填,指定缓存数据存放在哪块命名空间(缓存名)。用于指定要操作的缓存名称或缓存管理器的名称。可以是一个字符串,也可以是一个字符串数组,用于指定多个缓存名称。
  • cacheNames:与 value 差不多,二选一即可。
  • key:可选,指定缓存条目的键,用于唯一标识缓存中的条目。SpEL 表达式可以用于动态地生成键值。如果不指定 key,Spring Cache 将会使用默认的键生成策略来生成键值。
  • condition:条件符合则缓存。指定一个 SpEL 表达式,用于判断是否执行缓存操作。只有当表达式的值为 true 时,才会执行缓存操作。默认为空,表示始终执行缓存操作。
  • unless:条件符合则不缓存。指定一个 SpEL 表达式,用于判断是否不执行缓存操作。只有当表达式的值为 false 时,才会执行缓存操作。默认为空,表示始终执行缓存操作

@CacheEvict 、@Caching的使用:

@CacheEvict 代表当前方法如果执行,则删除指定的缓存;一般用于更新接口。

查询接口搭配使用 @Cacheable注解,等触发查询接口时,重新将数据库中新数据缓存起来,@CacheEvict 注解的作用相当于缓存中的“失效模式”。

//1、指定删除“category"缓存分区里,某个缓存key的数据。
@CacheEvict(value = {"category"},key = "'getLevel1Categorys'")

//2、指定删除“category"缓存分区里,某个缓存 key1、key2...keyN 的数据 (批量删)。
@Caching(evict = {
    @CacheEvict(value = {"category"}, key = "'getLevel1Categorys'"),
    @CacheEvict(value = {"category"}, key = "'getCatelogJson'"),
    // @CacheEvict(....) 可以删除多个
	}
)

//3、指定删除“category"缓存分区所有数据。比 (2)的删除方式更方便快捷,批量删推荐使用这种方式。
@CacheEvict(value = {"category"},allEntries = true)
@Transactional
@Override
public void updateCascade(CategoryVo categoryVo) {
  //略
}

//代表当前方法的结果需要缓存,如果缓存中有,方法不用调用。如果缓存中没有会调用方法,最后将方法的结果放入缓存
@Cacheable(value = {"category"}, key = "#root.methodName")
@Override
public List<CategoryEntity> getLevel1Categorys() {
    //略
}

@Cacheable(value = {"category"}, key = "#root.methodName")
@Override
public Map<String, List<Catelog2Vo>> getCatelogJson() {
    //略
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值