springboot(8)-多数据源-同一个redis地址的两个database

本文介绍如何在 Spring Boot 中配置多个 Redis 数据源,包括使用 JedisConnectionFactory 和 RedisTemplate 的具体步骤,以及如何通过 @Autowired 和 @Resource 注解区分不同数据源。

感谢大佬的参考文档:http://blog.51cto.com/13954634/2170900

https://blog.youkuaiyun.com/lc199408/article/details/77154375

总结:

 需要连接几个redis数据源,都可以只创建1个JedisConnectionFactory,其中JedisConnectionFactory使用 setdatabase、sethostName、setport等方法指定了访问Redis的哪个数据库。然后再创建多个RedisTemplate、StringRedisTemplate(两者的区别:https://blog.youkuaiyun.com/notsaltedfish/article/details/75948281)。使用@Autowired注解时,会自动创建一个实例,所以我们采用@Resource(name)会指定对应名称的@bean注解。

@Autowired
    @Resource(name="secondStringRedisTemplate")
    private StringRedisTemplate mStringRedisTemplate;
在运行上图时,由于碰到@Autowired,所以springboot会自动查找对应名称的@Bean:

    @Bean(name="secondStringRedisTemplate")
    public StringRedisTemplate secondStringRedisTemplate() {
        Object template;
        template = new StringRedisTemplate();
        ((StringRedisTemplate) template).setConnectionFactory(secondConnectionFactory());
        return (StringRedisTemplate) template;
    }
 
    public JedisConnectionFactory secondConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory(jedisPoolConfig());
        ((JedisConnectionFactory)factory).setHostName(RedisProperty.getHostName);
        ((JedisConnectionFactory)factory).setPort(RedisProperty);
        ((JedisConnectionFactory)factory).setDatabase(RedisProperty);
        ((JedisConnectionFactory)factory).setPoolConfig(PoolConfig());
        return factory;
    }
然后生成对应的template,上面的代码中通过prefix自动匹配到数据源,而@Autowired会自动将配置项set方法自动设置RedisProperty(需要创建这个类):

@ConfigurationProperties(prefix = "spring.redis")//不确定需不需要加prefix,可以试试
//如果加上这个会匹配到spring.redis配置并set各属性,但是jedisConnectionfactory(template不能覆盖)的prefix=spring.redis2可以覆盖这里的redis,会将redis2的配置set到各属性中。
public class RedisProperty {
    private String hostName;
    private int port;
    private String password;
 
    public String getHostName() {
        return this.hostName;
    }
 
    public int getPort() {
        return this.port;
    }
 
    public int getDatabase() {
        return this.database;
    }
}
然后又运行到setConnectionFactory(secondConnectionFactory()),其中secondConnectionFactory()函数指定了对应地址的redis(通过RedisProperty.getdatabase等方法),这样就可以实现使用不同的redis数据源。

实战一:

application.properties:

## Redis 配置
## Redis数据库索引(默认为0)
spring.redis.database=0
## Redis服务器地址
spring.redis.host=xxx
## Redis服务器连接端口
spring.redis.port=6379
# 连接超时时间(毫秒)
spring.redis.timeout=5000
 
 
## Redis 配置
## Redis数据库索引(默认为0)
spring.redis2.database=1
## Redis服务器地址
spring.redis2.host=xxx
## Redis服务器连接端口
spring.redis2.port=6379
# 连接超时时间(毫秒)
spring.redis2.timeout=5000
然后创建redisProperty.class:在这里匹配了redis的数据源地址1

@ConfigurationProperties(prefix = "spring.redis")//不确定需不需要加prefix,可以试试
//如果加上这个会匹配到spring.redis配置并set各属性,但是jedisConnectionfactory(template不能覆盖)的prefix=spring.redis2可以覆盖这里的redis,会将redis2的配置set到各属性中。
public class RedisProperty {
    private String hostName;
    private int port;
    private String password;
 
    public String getHostName() {
        return this.hostName;
    }
 
    public int getPort() {
        return this.port;
    }
 
    public int getDatabase() {
        return this.database;
    }
}
然后创建redisConfig:

创建StringredisTemplate,设置beanname(一定要设置,因为创建实例时,需要匹配beanname):

 @Bean(name="RedisTemplate")
    @ConditionalOnBean({RedisConnectionFactory.class})
    public RedisTemplate<Object, Object> RedisTemplate() {
        Object template;
        template = new RedisTemplate();
        ((RedisTemplate) template).setConnectionFactory(RedisConnectionFactory());
        return (RedisTemplate) template;
    }
    @Bean(name="StringRedisTemplate")
    public StringRedisTemplate StringRedisTemplate() {
        Object template;
        template = new StringRedisTemplate();
        ((StringRedisTemplate) template).setConnectionFactory(RedisConnectionFactory());
        return (StringRedisTemplate) template;
    }
创建RedisConnectionFactory:

    public JedisConnectionFactory RedisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory(jedisPoolConfig());
        ((JedisConnectionFactory)factory).setHostName(RedisProperty.getHostName);
        ((JedisConnectionFactory)factory).setPort(RedisProperty);
        ((JedisConnectionFactory)factory).setDatabase(RedisProperty);
        ((JedisConnectionFactory)factory).setPoolConfig(PoolConfig());
        return factory;
    }
然后创建一个controller:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
 
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
 
@RestController
public class Getxxx {
    @Autowired
    @Resource(name="StringRedisTemplate")
    private StringRedisTemplate mStringRedisTemplate;
 
    @GetMapping(value = xxx)
    public String getxxx(
          mStringRedisTemplate.delete(key);
            mStringRedisTemplate.opsForValue().set(key,value)
 
    }
}
使用第二个redis操作:

在redisConfig创建SecondStringredisTemplate,设置beanname(一定要设置,因为创建实例时,需要匹配beanname):

 @Bean(name="SecondRedisTemplate")
    @ConditionalOnBean({RedisConnectionFactory.class})
    public RedisTemplate<Object, Object> RedisTemplate() {
        Object template;
        template = new RedisTemplate();
        ((RedisTemplate) template).setConnectionFactory(SecondRedisConnectionFactory());
        return (RedisTemplate) template;
    }
    @Bean(name="SecondStringRedisTemplate")
    public StringRedisTemplate StringRedisTemplate() {
        Object template;
        template = new StringRedisTemplate();
        ((StringRedisTemplate) template).setConnectionFactory(SecondRedisConnectionFactory());
        return (StringRedisTemplate) template;
    }
创建SecondRedisConnectionFactory:

    @Bean({"secondRedisConnectionFactory"})
    @ConfigurationProperties(prefix="spring.redis2")//匹配redis2,会覆盖RedisProperty的prefix
 public JedisConnectionFactory secondRedisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory(jedisPoolConfig());
        ((JedisConnectionFactory)factory).setHostName(RedisProperty.getHostName);
        ((JedisConnectionFactory)factory).setPort(RedisProperty);
        ((JedisConnectionFactory)factory).setDatabase(RedisProperty);
        ((JedisConnectionFactory)factory).setPoolConfig(PoolConfig());
        return factory;
    }
然后创建一个新的controller:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
 
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
 
@RestController
public class Getxxx {
    @Autowired
    @Resource(name="SecondStringRedisTemplate")
    private StringRedisTemplate mStringRedisTemplate;
 
    @GetMapping(value = xxx)
    public String getxxx(
          mStringRedisTemplate.delete(key);
            mStringRedisTemplate.opsForValue().set(key,value)
 
    }
}
这样使用不同的

@Autowired
    @Resource(name="SecondStringRedisTemplate")
    private StringRedisTemplate mStringRedisTemplate;

就可以达到使用不同的redis地址。

方法二:(比较科学)

创建RedisConfig.class:Template匹配redis配置源地址,然后传给ConnectionFactory函数中:

@Configuration
public class RedisDevConfiguration {
 
    @Bean(name = "redisTemplate")
    public StringRedisTemplate redisTemplate(
//可以把这一步的@value放在RedisProperty.class进行,设置setter和getter
@Value("${spring.redis.host}") String hostName,
            @Value("${spring.redis.port}") int port, @Value("${spring.redis.password}") String password,
            @Value("${spring.redis.database}") int index {
        StringRedisTemplate temple = new StringRedisTemplate();
        temple.setConnectionFactory(
                connectionFactory(hostName, port, password,index));
 
        return temple;
    }
 
    public RedisConnectionFactory connectionFactory(String hostName, int port, String password, int maxIdle,
            int maxTotal, int index, long maxWaitMillis, boolean testOnBorrow) {
        JedisConnectionFactory jedis = new JedisConnectionFactory();
        jedis.setHostName(hostName);
        jedis.setPort(port);
        if (StringUtils.isNotEmpty(password)) {
            jedis.setPassword(password);
        }
        if (index != 0) {
            jedis.setDatabase(index);
        }
        jedis.setPoolConfig(poolCofig(maxIdle, maxTotal, maxWaitMillis, testOnBorrow));
        // 初始化连接pool
        jedis.afterPropertiesSet();
        RedisConnectionFactory factory = jedis;
 
        return factory;
    }
 
    public JedisPoolConfig poolCofig(int maxIdle, int maxTotal, long maxWaitMillis, boolean testOnBorrow) {
        JedisPoolConfig poolCofig = new JedisPoolConfig();
        poolCofig.setMaxIdle(maxIdle);
        poolCofig.setMaxTotal(maxTotal);
        poolCofig.setMaxWaitMillis(maxWaitMillis);
        poolCofig.setTestOnBorrow(testOnBorrow);
        return poolCofig;
    }
}
如果需要加上另一个redis(需要几个redis,就创建几个redisTemplate):

就添加:

 @Bean(name = "redis2Template")
    public StringRedisTemplate secondredisTemplate(@Value("${spring.redis2.host}") String hostName,
            @Value("${spring.redis.port}") int port, @Value("${spring.redis.password}") String password,
            @Value("${spring.redis2.database}") int index {
        StringRedisTemplate temple = new StringRedisTemplate();
        temple.setConnectionFactory(
                connectionFactory(hostName, port, password, maxIdle, maxTotal, index, maxWaitMillis, testOnBorrow));
        return temple;
    }
同理,创建Controller:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
 
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
 
@RestController
public class Getxxx {
    @Autowired
    @Resource(name="redisTemplate")//或者是redis2Template
    private StringRedisTemplate mStringRedisTemplate;
 
    @GetMapping(value = xxx)
    public String getxxx(
          mStringRedisTemplate.delete(key);
            mStringRedisTemplate.opsForValue().set(key,value)
 
    }
}
这样使用不同的

@Autowired
    @Resource(name="SecondStringRedisTemplate")
    private StringRedisTemplate mStringRedisTemplate;

就可以达到使用不同的redis地址。


原文链接:https://blog.youkuaiyun.com/qq_38204134/article/details/84859875

### Spring Boot Redis 多数据源配置实现方案 在Spring Boot项目中,为了满足多Redis数据源的需求,可以通过自定义`RedisConnectionFactory`以及`RedisTemplate`来实现不同Redis实例的操作。以下是具体的实现方法: #### 1. 添加依赖 确保项目的`pom.xml`文件中已包含必要的依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 此部分无需额外说明,因为这是标准的Spring Boot Redis集成方式[^4]。 --- #### 2. 配置多个Redis连接信息 通过`application.yml`或`application.properties`文件配置多个Redis的数据源信息。例如,在`application.yml`中可如下设置: ```yaml spring: redis: master: host: localhost port: 6379 password: database: 0 slave: host: localhost port: 6380 password: database: 1 ``` 上述配置分别指定了两个Redis实例的信息:一个是主数据库(`master`),另一个是从数据库(`slave`)。这种配置方式简单明了,并且便于维护[^2]。 --- #### 3. 创建自定义Redis连接工厂 由于需要支持多数据源,因此需创建多个`RedisConnectionFactory`实例。以下是一个通用的工厂类模板: ```java import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; @Configuration public class RedisConfig { @Bean(name = "masterRedisConnectionFactory") public LettuceConnectionFactory masterRedisConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName("localhost"); config.setPort(6379); config.setPassword(null); // 设置密码 config.setDatabase(0); // 数据库编号 return new LettuceConnectionFactory(config, lettuceClientConfiguration()); } @Bean(name = "slaveRedisConnectionFactory") public LettuceConnectionFactory slaveRedisConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName("localhost"); config.setPort(6380); config.setPassword(null); // 设置密码 config.setDatabase(1); // 数据库编号 return new LettuceConnectionFactory(config, lettuceClientConfiguration()); } private LettuceClientConfiguration lettuceClientConfiguration() { return LettuceClientConfiguration.builder().build(); } } ``` 以上代码展示了如何基于Lettuce驱动程序构建两个独立的`RedisConnectionFactory`实例,分别为`masterRedisConnectionFactory`和`slaveRedisConnectionFactory`[^3]。 --- #### 4. 配置多个RedisTemplate实例 为了让业务逻辑能够区分访问不同的Redis实例,还需要为每个`RedisConnectionFactory`绑定对应的`RedisTemplate`对象: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.RedisTemplate; @Configuration public class RedisTemplateConfig { @Bean(name = "masterRedisTemplate") public RedisTemplate<String, Object> masterRedisTemplate( @Qualifier("masterRedisConnectionFactory") LettuceConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); return template; } @Bean(name = "slaveRedisTemplate") public RedisTemplate<String, Object> slaveRedisTemplate( @Qualifier("slaveRedisConnectionFactory") LettuceConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); return template; } } ``` 这里的关键在于使用`@Qualifier`注解指定特定的`RedisConnectionFactory`实例,从而避免混淆[^5]。 --- #### 5. 使用RedisTemplate操作Redis 在实际开发过程中,可以直接注入所需的`RedisTemplate`实例并执行相应操作。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class RedisService { @Autowired @Qualifier("masterRedisTemplate") private RedisTemplate<String, Object> masterRedisTemplate; @Autowired @Qualifier("slaveRedisTemplate") private RedisTemplate<String, Object> slaveRedisTemplate; public void saveToMaster(String key, String value) { masterRedisTemplate.opsForValue().set(key, value); } public String getFromSlave(String key) { return (String) slaveRedisTemplate.opsForValue().get(key); } } ``` 该示例清晰地演示了如何针对不同Redis实例进行读写分离操作。 --- ### 注意事项 1. **序列化问题** 默认情况下,`RedisTemplate`可能无法正确处理复杂类型的序列化/反序列化。建议显式配置其键值序列化器。 2. **数据库编号冲突** 不同Redis实例间应严格划分使用的数据库编号,防止意外覆盖数据。 3. **自动装配干扰** 若项目已有默认的Redis配置,则新加入的多数据源配置可能会引发冲突。此时可通过排除`RedisAutoConfiguration`解决: ```java @EnableAutoConfiguration(exclude={RedisAutoConfiguration.class}) ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那些年的代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值