Spring Boot 教程

Spring Boot 笔记

Spring Boot 如何配置多个 Redis

Spring Boot 笔记 Spring Boot 笔记


Spring Boot 基于 lettuce 配置多个 Redis 连接,这里基于 jdk 1.8,引入 spring data redis 即可。具体配置步骤如下。

引入相关 jar 包

先引入 spring data redis 的 starter 包。

如果项目是 maven 项目,示例如下:

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

如果是 gradle 项目,示例如下:

compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'

配置数据源

配置多个 redis,首先要禁调 spring boot 默认的单 redis 配置,然后在 application.yml 里自定义配置多个 redis,最后创建基于注解的 redis 配置类。

禁止默认单数据源配置

spring boot 默认情况下,它会读取 application.yml 文件的 spring.redis.* 属性,并自动配置单 redis,需要通过以下方式禁止这一默认行为,具体如下:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {
        RedisAutoConfiguration.class,
        RedisRepositoriesAutoConfiguration.class,
        RedisReactiveAutoConfiguration.class
})
public class MainApplication {
    
    public static void main(String[] args) {
       
        SpringApplication.run(MainApplication.class, args);
        
    }
}

在 main 方法所在的类上面增加 @EnableAutoConfiguration 注解,并在其中排除(exclude)RedisAutoConfigurationRedisRepositoriesAutoConfigurationRedisReactiveAutoConfiguration 类即可。

application.yml 配置

在 application.yml 里配置多个 redis 数据源,名字无所谓,只需要不和 spring 默认的配置参数重名就可以,笔者以 redis 作为前缀,具体如下:

redis:
  lettuce:
    pool:
      maxTotal: 45
      maxIdle: 6
      maxWaitMillis: 30000
      minIdle: 2
  r1:
    hostName: xxx
    port: 6379
    password: xxx
  r2:
    hostName: xxx
    port: 6379
    password: xxx

其中 r1 和 r2 表示自定义的 redis 实例名称,笔者这里 redis 客户端使用了 lettuce,所以加了连接池相关参数的设置。

基于注解的 redis 配置类

创建如下类:

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
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.time.Duration;


@Configuration
public class RedisConfig {

    @Bean("redisPoolConfig")
    @ConfigurationProperties(prefix = "redis.lettuce.pool")
    @Scope(value = "prototype")
    public GenericObjectPoolConfig redisPoolConfig() {
        return new GenericObjectPoolConfig();
    }

    @Bean("r1RedisConfig")
    @ConfigurationProperties(prefix = "redis.r1")
    public RedisStandaloneConfiguration commonStandaloneConfiguration() {
        return new RedisStandaloneConfiguration();
    }

    @Bean("r1ConnectionFactory")
    public LettuceConnectionFactory commonConnectionFactory(
            @Qualifier("redisPoolConfig") GenericObjectPoolConfig redisPoolConfig,
            @Qualifier("r1RedisConfig") RedisStandaloneConfiguration redisConfig
    ) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration
                .builder()
                .poolConfig(redisPoolConfig)
                .commandTimeout(Duration.ofMillis(redisPoolConfig.getMaxWaitMillis()))
                .build();
        return new LettuceConnectionFactory(redisConfig, clientConfiguration);
    }

    @Bean("r1RedisTemplate")
    public RedisTemplate<String, Object> commonReactiveRedisTemplate(
            @Qualifier("r1ConnectionFactory") RedisConnectionFactory redisConnectionFactory
    ) {
        return redisTemplate(redisConnectionFactory);
    }

    @Bean("r2RedisConfig")
    @ConfigurationProperties(prefix = "redis.r2")
    public RedisStandaloneConfiguration featureStandaloneConfiguration() {
        return new RedisStandaloneConfiguration();
    }

    @Bean("r2ConnectionFactory")
    public LettuceConnectionFactory featureConnectionFactory(
            @Qualifier("redisPoolConfig") GenericObjectPoolConfig redisPoolConfig,
            @Qualifier("r2RedisConfig") RedisStandaloneConfiguration redisConfig
    ) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration
                .builder()
                .poolConfig(redisPoolConfig)
                .commandTimeout(Duration.ofMillis(redisPoolConfig.getMaxWaitMillis()))
                .build();
        return new LettuceConnectionFactory(redisConfig, clientConfiguration);
    }

    @Bean("r2RedisTemplate")
    public RedisTemplate<String, Object> featureReactiveRedisTemplate(
            @Qualifier("r2ConnectionFactory") RedisConnectionFactory redisConnectionFactory
    ) {
        return redisTemplate(redisConnectionFactory);
    }

    private RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisSerializer stringSerializer = new StringRedisSerializer();
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(stringSerializer);
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(stringSerializer);
        redisTemplate.setDefaultSerializer(stringSerializer);

        return redisTemplate;
    }

}

最后在使用处,通过注入相应的 RedisTemplate 即可使用:

    @Autowired
    @Qualifier("r1RedisTemplate")
    private RedisTemplate<String, Object> r1RedisTemplate;