(22.02.21)Redis配置多数据源

734 阅读2分钟

配置一个服务连接多个Redis

需求: 一个项目需要使用多个Redis来存储数据

SpringBoot项目中导入Redis依赖默认,在配置文件中只能配置一个Redis

导入依赖

        <!--线程池: https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.9.0</version>
        </dependency>

        <!-- redis: https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

编写配置文件

spring:
  #Springboot默认的Reids
  redis:
    host: localhost
    port: 6379
    timeout: 3000
    database: 1

  # 自定义的配置Redis,需要多个只需要在后继续追加
  redis-user:
    # Host
    host: localhost
    # 密码
    password:
    # 端口
    port: 6379
    # 数据库
    database: 2
    # 超时时间
    timeout: 3000
    # 连接池最大活跃连接数
    max-active: 100
    # 连接池最大建立连接等待时间, 单位为ms, 如果超过此时间将抛出异常
    max-wait: 3000
    # 连接池最大空闲连接数, 超过空闲数将被标记为不可用,然后被释放
    max-idle: 20
    # 连接池里始终应该保持的最小连接数
    min-idle: 0

编写Redis的配置类

由于第一个redis是springboot配置好的,因此无需配置

着重配置后面自定义的Redis连接

获取配置

首先需要获取到配置文件中的配置信息,这里有两种方法

  • 使用ConfigurationProperties,映射在实体类上,当配置较多时可以采用这种方法

    • 建立对应实体类 UserRedisProperties.class

      @Data
      @Component
      @ConfigurationProperties( prefix = "spring.redis-user")  // 通过该注解自动映射
      public class UserRedisProperties {
      
          /**
           * 配置里面的 '-' 转为驼峰即可读取配置
           */
      
          private String host;
          private String password;
          private int port;
          private int timeout;
          private int database;
          private int maxWait;
          private int maxActive;
          private int maxIdle;
          private int minIdle;
      }
      
    • 在配置类中通过对象获取值

      @Autowired
      private UserRedisProperties userRedisProperties;
      
      String host = userRedisProperties.gethost();  // 这样可以获取到配置中的值
      ...
          
      
  • 也可以使用@Value直接获取值再传入

        @Value("${spring.redis-user.database}")
        private int database;
    
        @Value("${spring.redis-user.host}")
        private String host;
    
        @Value("${spring.redis-user.port}")
        private int port;
    
        @Value("${spring.redis-user.password}")
        private String password;
    
        @Value("${spring.redis-user.timeout}")
        private int timeout;
    
        @Value("${spring.redis-user.max-active}")
        private int redisPoolMaxActive;
    
        @Value("${spring.redis-user.max-wait}")
        private int redisPoolMaxWait;
    
        @Value("${spring.redis-user.max-idle}")
        private int redisPoolMaxIdle;
    
        @Value("${spring.redis-user.min-idle}")
        private int redisPoolMinIdle;
    

编写配置具体信息

每个Redis对应一个配置文件,这里以第一种方式获取配置

@Configuration
@EnableCaching
public class RedisConfigure extends CachingConfigurerSupport {

    @Autowired
    private UserRedisProperties userRedisProperties;

    /**
     * @Bean:
     * 1: 这里声明该方法返回的是受Spring容器管理的Bean
     * 2: 方法名与返回类名一致,但首字母小写:为redisTemplateUser
     */

    @Bean
    public RedisTemplate redisTemplateUser() {

        // 基本配置
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(userRedisProperties.getHost());
        configuration.setPort(userRedisProperties.getPort());
        configuration.setDatabase(userRedisProperties.getDatabase());
        if (Strings.isNotBlank(userRedisProperties.getPassword())) {
            configuration.setPassword(RedisPassword.of(userRedisProperties.getPassword()));
        }

        // 连接池配置
        GenericObjectPoolConfig<Object> genericObjectPoolConfig = new GenericObjectPoolConfig<>();
        genericObjectPoolConfig.setMaxTotal(userRedisProperties.getMaxActive());
        genericObjectPoolConfig.setMaxWaitMillis(userRedisProperties.getMaxWait());
        genericObjectPoolConfig.setMaxIdle(userRedisProperties.getMaxIdle());
        genericObjectPoolConfig.setMinIdle(userRedisProperties.getMinIdle());

        // lettuce pool
        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
        builder.poolConfig(genericObjectPoolConfig);
        builder.commandTimeout(Duration.ofSeconds(userRedisProperties.getTimeout()));
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(configuration, builder.build());

        lettuceConnectionFactory.afterPropertiesSet();
        return createRedisTemplate(lettuceConnectionFactory);
    }

    private <T> RedisTemplate<String, T> createRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, T> stringObjectRedisTemplate = new RedisTemplate<>();
        stringObjectRedisTemplate.setConnectionFactory(redisConnectionFactory);

        RedisSerializer<String> redisSerializer = new StringRedisSerializer();

        // key序列化
        stringObjectRedisTemplate.setKeySerializer(redisSerializer);
        // value序列化
        stringObjectRedisTemplate.setValueSerializer(redisSerializer);
        // value hashMap序列化
        stringObjectRedisTemplate.setHashValueSerializer(redisSerializer);
        // key haspMap序列化
        stringObjectRedisTemplate.setHashKeySerializer(redisSerializer);

        return stringObjectRedisTemplate;
    }
}

使用RedisTemplate操作Redis

因为存在多个RedisTemplate,所以在自动注入时只能byName而不能byType

  • 使用@Autowire注解

    @Autowire默认是ByName,通过加 @Qualifier指定名称可实现通过名称注入

    @Qualifier("redisTemplateUser")
    @Autowired
    private RedisTemplate<String, String> redisTemplateUser;
    redisTemplateUser.opsForValue().set("redisTemplateUser", "success");
    
  • 使用@Resource注解

    @Resource(name = "redisTemplateUser")
    RedisTemplate<String, Object> redisTemplateUser;
    redisTemplateUser.opsForValue().set("redisTemplateUser", "success");
    

参考博客

参考源码