介绍

在SpringBoot中一般使用RedisTemplate提供的方法来操作Redis

SpringBoot 2.x后 ,原来底层使用的 Jedis 被 lettuce[赖忒死] 替换。所以在springboot中引入spring-boot-starter-data-redis依赖时,默认使用的时Lettuce。

  • jedis:采用的直连,多个线程操作的话,是不安全的。如果要避免不安全,使用jedis pool连接池!更像BIO模式(阻塞模式)。
  • lettuce:采用netty(高性能网络框架,异步请求),实例可以在多个线程中共享,不存在线程不安全的情况!可以减少线程数量了,更像NIO模式。

而我们要是使用的是StringRedisTemplate 而不是 RedisTemplate

StringRedisTemplate是RedisTemplate的子类(不代表value只能是string,而是序列化策略为StringRedisSerializer)

  • RedisTemplate默认采用的是JDK的序列化策略,即JdkSerializationRedisSerializer,保存的key和value都是采用此策略序列化保存的。比如说存入数据会将数据先序列化成字节数组然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式展现的,而是以字节数组显示,类似下面,当然从Redis获取数据的时候也会默认将数据当做字节数组转化。

RedisTemplate的multiGet redistemplate的multiget的性能_spring boot

  • StringRedisTemplate的API假定所有的数据类型化都是字符类型,即key和value都是字符串类型。默认采用的是String的序列化策略,即StringRedisSerializer,保存的key和value都是采用此策略序列化保存的。

RedisTemplate的multiGet redistemplate的multiget的性能_连接池_02

作用

redis连接数据库,可以实现排行榜(有序集合),缓存(字符串类型)等功能

快速开始

导入依赖

<!--redis场景启动器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis 连接池 -->
<!--新版本连接池lettuce-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

配置文件

#****************************redis****************************
# Redis数据库索引(默认为0)
redis: 
  database:
    # 默认库
    default: 0
    # 缓存库
    cache: 1
    # 排行榜库
    sort: 2
    # 搜索历史的库
    history: 3
    
spring:
  redis:
    host: 127.0.0.1
    lettuce:
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 20
        # 连接池中的最大空闲连接
        max-idle: 10
        # 连接池中的最小空闲连接
        min-idle: 5
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: 5000
    # Redis服务器连接密码(默认为空,代表没有密码)
    password: 10401
    # Redis服务器连接端口
    port: 6379
    # 连接超时时间(毫秒)
    timeout: 5000

配置类

import io.lettuce.core.resource.DefaultClientResources;
 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.data.redis.connection.RedisPassword;
 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.StringRedisTemplate;
 import org.springframework.util.ObjectUtils;
 
 import java.time.Duration;
 
 @Configuration
 public class RedisConfig {
 
     @Value("${redis.database.default}")
     private int defaultDataBase;
 
     @Value("${redis.database.sort}")
     private int sortDataBase;
 
     @Value("${redis.database.cache}")
     private int drugCacheDataBase;
 
     @Value("${redis.database.history}")
     private int historyDataBase;
 
     @Value("${spring.redis.host}")
     private String host;
 
     @Value("${spring.redis.port}")
     private int port;
 
     @Value("${spring.redis.password}")
     private String password;
 
     @Value("${spring.redis.lettuce.pool.max-active}")
     private int maxActive;
 
     @Value("${spring.redis.lettuce.pool.max-wait}")
     private int maxWait;
 
     @Value("${spring.redis.lettuce.pool.max-idle}")
     private int maxIdle;
 
     @Value("${spring.redis.lettuce.pool.min-idle}")
     private int minIdle;
 
     @Value("${spring.redis.timeout}")
     private long timeout;
     
     /**
      * 配置redis连接池
      */
     @Bean
     public GenericObjectPoolConfig poolConfig() {
         GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
         poolConfig.setMaxTotal(maxActive);
         poolConfig.setMaxIdle(maxIdle);
         poolConfig.setMinIdle(minIdle);
         poolConfig.setMaxWaitMillis(maxWait);
         return poolConfig;
     }
     
     /**
      * 配置默认客户端资源
      */
     @Bean("defaultClientResources")
     public  DefaultClientResources getDefaultClientResources(){
         return DefaultClientResources.create();
     }

     private StringRedisTemplate getStringRedisTemplate(int database, GenericObjectPoolConfig poolConfig, DefaultClientResources defaultClientResources) {
         // 构建工厂对象
         RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
         config.setHostName(host);
         config.setPort(port);
         if (!ObjectUtils.isEmpty(password)) {
             RedisPassword redisPassword = RedisPassword.of(password);
             config.setPassword(redisPassword);
         }
         LettucePoolingClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                 .commandTimeout(Duration.ofSeconds(timeout))
                 .poolConfig(poolConfig)
                 .clientResources(defaultClientResources)
                 .build();
         LettuceConnectionFactory factory = new LettuceConnectionFactory(config, clientConfig);
         // 设置使用的redis数据库
         factory.setDatabase(database);
         // 重新初始化工厂
         factory.afterPropertiesSet();
         return new StringRedisTemplate(factory);
     }
 
     @Bean(name="redisTemplateDefault")
     public StringRedisTemplate redisTemplateDefault(GenericObjectPoolConfig poolConfig,
                     @Qualifier("defaultClientResources") DefaultClientResources defaultClientResources) {
         return getStringRedisTemplate(defaultDataBase, poolConfig,defaultClientResources);
     }
 
     @Bean(name="redisTemplateSort")
     public StringRedisTemplate redisTemplateSort(GenericObjectPoolConfig poolConfig,
                                                  @Qualifier("defaultClientResources") DefaultClientResources defaultClientResources) {
         return getStringRedisTemplate(sortDataBase, poolConfig,defaultClientResources);
     }
 
     @Bean(name="redisTemplateDrugCache")
     public StringRedisTemplate redisTemplateCacheDrug(GenericObjectPoolConfig poolConfig,
                                              @Qualifier("defaultClientResources") DefaultClientResources defaultClientResources) {
         return getStringRedisTemplate(drugCacheDataBase, poolConfig,defaultClientResources);
     }
 
     @Bean(name="redisTemplateHistory")
     public StringRedisTemplate redisTemplateHistory(GenericObjectPoolConfig poolConfig,
                                                       @Qualifier("defaultClientResources") DefaultClientResources defaultClientResources) {
         return getStringRedisTemplate(historyDataBase, poolConfig,defaultClientResources);
     }
 }

一总往Spring容器注入了四个StringRedisTemplate对象,分别对应操作不同的库

使用

指定名称的从IOC容器获取,因为配置了多个对象

@Resource(name = "redisTemplateDefault")
private StringRedisTemplate stringRedisTemplate;