Spring Boot 整合多 Redis 数据源配置及操作
简介
本文档介绍了如何在Spring Boot应用程序中配置和操作多个Redis数据源。通过配置多个RedisConnectionFactory和RedisTemplate,可以实现对多个Redis数据源的整合,以便在应用程序中灵活地使用不同的Redis实例。
以下是本文档的主要内容:
- 添加依赖:介绍了在pom.xml文件中添加Spring Boot和Redis相关依赖的步骤。
- 配置多个Redis数据源:说明了如何在application.properties或application.yml中配置多个Redis数据源的连接信息。
- 创建多个RedisConnectionFactory:展示了在配置类中创建多个RedisConnectionFactory的Bean,并分别指定不同连接信息的步骤。
- 创建多个RedisTemplate:介绍了根据不同的RedisConnectionFactory创建对应的RedisTemplate的步骤。
- 使用多个RedisTemplate进行操作:说明了在需要使用Redis的地方,如何注入对应的RedisTemplate,并使用它们来操作不同的Redis数据源。
通过本文档的指导,您将能够轻松地在Spring Boot应用程序中实现对多个Redis数据源的整合配置和操作,从而满足不同业务场景下对多个Redis实例的需求。
代码实现
配置POM依赖
<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>
配置多个Redis数据源
spring:
redis:
host: localhost
port: 6379
database: 0
password: 123456
lettuce: # 使用Lettuce作为Redis的客户端
pool: # 连接池
max-active: 32 # 最大的活跃连接数
max-wait: 300 # 获取连接的最大等待时间
max-idle: 16 # 最大的空闲连接数
min-idle: 8 # 最小的空闲连接数
redis-node02:
host: localhost
port: 6379
database: 1
password: 123456
lettuce:
pool:
max-active: 16
max-wait: 100
max-idle: 8
min-idle: 4
创建多个Redis连接配置
- 读取配置信息
- 初始化ConnectionFactory
- 创建RedisTemplate实例
@Configuration
public class RedisAutoConfig {
@Bean
@Primary
public LettuceConnectionFactory defaultLettuceConnectionFactory(RedisStandaloneConfiguration defaultRedisConfig,
GenericObjectPoolConfig defaultPoolConfig) {
LettuceClientConfiguration clientConfig =
LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(100))
.poolConfig(defaultPoolConfig).build();
return new LettuceConnectionFactory(defaultRedisConfig, clientConfig);
}
@Bean
public RedisTemplate<String, String> defaultRedisTemplate(
@Qualifier("defaultLettuceConnectionFactory") LettuceConnectionFactory defaultLettuceConnectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(defaultLettuceConnectionFactory);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
@ConditionalOnBean(name = "node02RedisConfig")
public LettuceConnectionFactory node02LettuceConnectionFactory(RedisStandaloneConfiguration node02RedisConfig,
GenericObjectPoolConfig node02PoolConfig) {
LettuceClientConfiguration clientConfig =
LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(100))
.poolConfig(node02PoolConfig).build();
return new LettuceConnectionFactory(node02RedisConfig, clientConfig);
}
@Bean
@ConditionalOnBean(name = "node02LettuceConnectionFactory")
public RedisTemplate<String, String> node02RedisTemplate(
@Qualifier("node02LettuceConnectionFactory") LettuceConnectionFactory node02LettuceConnectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(node02LettuceConnectionFactory);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 默认配置
*/
@Configuration
public static class DefaultRedisConfig {
@Value("${spring.redis.host:127.0.0.1}")
private String host;
@Value("${spring.redis.port:6379}")
private Integer port;
@Value("${spring.redis.password:}")
private String password;
@Value("${spring.redis.database:0}")
private Integer database;
@Value("${spring.redis.lettuce.pool.max-active:8}")
private Integer maxActive;
@Value("${spring.redis.lettuce.pool.max-wait:-1}")
private Long maxWait;
@Value("${spring.redis.lettuce.pool.max-idle:8}")
private Integer maxIdle;
@Value("${spring.redis.lettuce.pool.min-idle:0}")
private Integer minIdle;
@Bean
public GenericObjectPoolConfig defaultPoolConfig() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(maxActive);
config.setMaxWaitMillis(maxWait);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
return config;
}
@Bean
public RedisStandaloneConfiguration defaultRedisConfig() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setPassword(RedisPassword.of(password));
config.setDatabase(database);
return config;
}
}
/**
* Node02配置
*/
@Configuration
public static class Node02RedisConfig {
@Value("${spring.redis-node02.host:127.0.0.1}")
private String host;
@Value("${spring.redis-node02.port:6379}")
private Integer port;
@Value("${spring.redis-node02.password:}")
private String password;
@Value("${spring.redis-node02.database:0}")
private Integer database;
@Value("${spring.redis-node02.lettuce.pool.max-active:8}")
private Integer maxActive;
@Value("${spring.redis-node02.lettuce.pool.max-wait:-1}")
private Long maxWait;
@Value("${spring.redis-node02.lettuce.pool.max-idle:8}")
private Integer maxIdle;
@Value("${spring.redis-node02.lettuce.pool.min-idle:0}")
private Integer minIdle;
@Bean
public GenericObjectPoolConfig node02PoolConfig() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(maxActive);
config.setMaxWaitMillis(maxWait);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
return config;
}
@Bean
public RedisStandaloneConfiguration node02RedisConfig() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setPassword(RedisPassword.of(password));
config.setDatabase(database);
return config;
}
}
}
如果不借助@Primary
来指定默认的连接工厂,就会报错如下打印信息:
Description:
Parameter 0 of method reactiveRedisTemplate in org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration required a single bean, but 2 were found:
- defaultLettuceConnectionFactory: defined by method 'defaultLettuceConnectionFactory' in class path resource [com/itwenke/springbootdemo/redismultiple/config/RedisAutoConfig.class]
- node02LettuceConnectionFactory: defined by method 'node02LettuceConnectionFactory' in class path resource [com/itwenke/springbootdemo/redismultiple/config/RedisAutoConfig.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
使用多个RedisTemplate进行操作
- 写操作
- 读操作
@RestController
@RequestMapping(path = {"api/test"})
public class TestController {
@Resource
private RedisTemplate<String, String> defaultRedisTemplate;
@Resource
private RedisTemplate<String, String> node02RedisTemplate;
@GetMapping(path = "set")
public void set() {
defaultRedisTemplate.opsForValue().set("key1", "value1");
node02RedisTemplate.opsForValue().set("key2", "value2");
}
@GetMapping(path = "get")
public void get() {
String value1 = defaultRedisTemplate.opsForValue().get("key1");
String value2 = node02RedisTemplate.opsForValue().get("key2");
System.out.println("value1 = " + value1 + ", value2 = " + value2);
}
}
开始测试
查询数据库
数据库0和1都为空,因为还没添加数据
执行set写操作
http://localhost:8080/api/test/set
可以查看到数据库0和1都添加了对应的数据
执行get读操作
http://localhost:8080/api/test/get
控制台打印信息:value1 = value1, value2 = value2