在一个项目中配置多个 RedisTemplate 是常见需求,例如连接不同的 Redis 服务器、不同的数据库,或为不同业务定制不同的序列化方式。Spring Data Redis 提供了灵活的配置方式,允许我们定义多个 RedisConnectionFactory 和对应的 RedisTemplate Bean,并通过 @Qualifier 在注入时区分。
下面给出一个完整的配置方案,包括基于 YAML 的多数据源定义和 Java 配置类的实现。
1. 依赖准备
确保已引入 Spring Data Redis 和连接池依赖(以 Lettuce 为例):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2. YAML 中定义多个 Redis 连接信息
在 application.yml 中可以为不同的 Redis 数据源分别配置连接参数,使用自定义前缀:
spring:
# 默认数据源(可选,也可以不用)
redis:
host: localhost
port: 6379
database: 0
lettuce:
pool:
max-active: 8
# 自定义数据源1
redis1:
host: redis1.example.com
port: 6379
password: pass1
database: 1
lettuce:
pool:
max-active: 16
max-idle: 8
min-idle: 2
# 自定义数据源2
redis2:
host: redis2.example.com
port: 6380
password: pass2
database: 2
lettuce:
pool:
max-active: 16
max-idle: 8
min-idle: 2
3. Java 配置类:创建多个 RedisConnectionFactory 和 RedisTemplate
创建一个配置类 MultipleRedisConfig,通过 @ConfigurationProperties 读取自定义前缀的配置,并为每个数据源创建独立的 LettuceConnectionFactory 和 RedisTemplate。
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
public class MultipleRedisConfig {
// ---------- 第一个数据源 ----------
@Bean
@ConfigurationProperties(prefix = "redis1") // 绑定 YAML 中以 redis1 开头的属性
public RedisProperties redis1Properties() {
return new RedisProperties(); // 复用 Spring Boot 的 RedisProperties 类
}
@Bean
public LettuceConnectionFactory redis1ConnectionFactory() {
RedisProperties props = redis1Properties();
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(props.getHost());
config.setPort(props.getPort());
config.setPassword(props.getPassword());
config.setDatabase(props.getDatabase());
// 连接池配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(props.getLettuce().getPool().getMaxActive());
poolConfig.setMaxIdle(props.getLettuce().getPool().getMaxIdle());
poolConfig.setMinIdle(props.getLettuce().getPool().getMinIdle());
poolConfig.setMaxWait(Duration.ofMillis(props.getLettuce().getPool().getMaxWait().toMillis()));
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.poolConfig(poolConfig)
.build();
return new LettuceConnectionFactory(config, clientConfig);
}
@Bean
public RedisTemplate<String, Object> redis1Template() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redis1ConnectionFactory());
// 设置序列化方式
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
// ---------- 第二个数据源 ----------
@Bean
@ConfigurationProperties(prefix = "redis2")
public RedisProperties redis2Properties() {
return new RedisProperties();
}
@Bean
public LettuceConnectionFactory redis2ConnectionFactory() {
// 与第一个类似,从 redis2Properties() 读取配置
RedisProperties props = redis2Properties();
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(props.getHost());
config.setPort(props.getPort());
config.setPassword(props.getPassword());
config.setDatabase(props.getDatabase());
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(props.getLettuce().getPool().getMaxActive());
poolConfig.setMaxIdle(props.getLettuce().getPool().getMaxIdle());
poolConfig.setMinIdle(props.getLettuce().getPool().getMinIdle());
poolConfig.setMaxWait(Duration.ofMillis(props.getLettuce().getPool().getMaxWait().toMillis()));
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.poolConfig(poolConfig)
.build();
return new LettuceConnectionFactory(config, clientConfig);
}
@Bean
public RedisTemplate<String, Object> redis2Template() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redis2ConnectionFactory());
// 可以设置不同的序列化方式,这里与第一个相同
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
// 如果还需要默认的 RedisTemplate(基于 spring.redis 配置),可以另外配置
// 注意:需要处理主数据源的 @Primary
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.redis")
public RedisProperties defaultRedisProperties() {
return new RedisProperties();
}
@Bean
@Primary
public LettuceConnectionFactory defaultRedisConnectionFactory() {
// 类似构造,使用 defaultRedisProperties()
// ...
return factory;
}
@Bean
@Primary
public RedisTemplate<String, Object> defaultRedisTemplate() {
// ...
return template;
}
}
注意:
RedisProperties是 Spring Boot 内置的配置类,可以直接使用。上面的代码中通过@ConfigurationProperties绑定自定义前缀,完美复用现有属性类。
4. 使用多个 RedisTemplate
在 Service 中通过 @Qualifier 指定要注入的 Bean:
@Service
public class MyService {
@Autowired
@Qualifier("redis1Template")
private RedisTemplate<String, Object> redis1Template;
@Autowired
@Qualifier("redis2Template")
private RedisTemplate<String, Object> redis2Template;
public void demo() {
redis1Template.opsForValue().set("key1", "value from redis1");
redis2Template.opsForValue().set("key2", "value from redis2");
}
}
5. 扩展:支持 Redis 集群或哨兵
如果某个数据源是集群模式,可以将 RedisStandaloneConfiguration 替换为 RedisClusterConfiguration 或 RedisSentinelConfiguration,并使用对应的构造方法。例如:
RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration()
.clusterNode("host1", 6379)
.clusterNode("host2", 6379);
然后在创建 LettuceConnectionFactory 时传入该配置。
6. 注意事项
- 连接池:每个
LettuceConnectionFactory拥有独立的连接池,配置时注意内存和资源开销。 - 事务:如果需要支持 Redis 事务,需在
RedisTemplate上设置setEnableTransactionSupport(true)。 - 序列化:根据业务需求选择合适的序列化方式(如 Jackson、JdkSerializationRedisSerializer、StringRedisSerializer 等)。注意跨语言兼容性和性能。
- 默认 Bean:如果只配置了多个
RedisTemplate,而没有@Primary标记,Spring 会因类型冲突而报错。要么指定一个@Primary,要么在注入时始终使用@Qualifier明确指定。 - 配置文件结构:上述代码假设我们的 YAML 结构与
RedisProperties一致。如果自定义字段,可以创建自己的配置类。
通过以上方案,我们可以灵活地在一个项目中管理多个 Redis 数据源,满足各种业务隔离或异构需求。
