Java SpringBoot配置Redis多数据源

前段时间写一个项目,有一个功能实时性要求比较高,而且读写操作也很频繁,最后决定逻辑层使用 Redis 支持,当流程结束后再做数据持久化。因为高并发,且该功能数据比较独立,所以采用了一个单独的 Redis 数据源,跟主流程的 Redis 分开。

这里简单写一个 SpringBoot 配置 Redis 多数据源的 Demo 记录一下。

pom.xml 文件引入 Redis 依赖:spring-boot-starter-data-redis 线程池:commons-pool2 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependencies>
  ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <version>2.1.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.9.0</version>
    </dependency>
  ...
</dependencies>

既然是多数据源,就需要配置两个 Redis 数据源。在 application.yml 或 application.properties 添加配置,本篇使用 application.yml  文件:

1: 配置一个端口为 6379 的默认 Redis;

2: 配置一个端口为 6380 的 UserRedis;连接池的配置写在上面和下面都行,初始化的时候能读取到就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
spring:
  redis:
    host: localhost
    port: 6379
    timeout: 3000
    database: 0<br>
  # 第二个redis配置
  redis-user:
    # Host
    host: localhost
    # 密码
    password:
    # 端口
    port: 6380
    # 超时时间
    timeout: 3000
    # 数据库
    database: 0
    # 连接池最大活跃连接数
    max-active: 100
    # 连接池最大建立连接等待时间, 单位为ms, 如果超过此时间将抛出异常
    max-wait: 3000
    # 连接池最大空闲连接数, 超过空闲数将被标记为不可用,然后被释放
    max-idle: 20
    # 连接池里始终应该保持的最小连接数
    min-idle: 0

因为这里拟定第二个 Redis 数据源是为 User 逻辑服务的,所以创建一个读取 UserRedis 配置类:

UserRedisProperties.java : 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.demo.redisdemo.config.redis;
 
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
/**
 * @author AnYuan
 */
 
@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;
}

接下来就是重点,总结来说就是读取 UserRedis 的配置,声明一个 @Bean ,设置好对应的参数,创建第二个 RedisTemplate。

创建一个初始化的配置类:RedisConfigure.java :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.demo.redisdemo.config.redis;
 
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
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;
 
/**
 * Redis 初始化配置
 * @author AnYuan
 */
 
@Configuration
@EnableCaching
public class RedisConfigure extends CachingConfigurerSupport {
 
    @Autowired
    private UserRedisProperties userRedisProperties;
 
    /**
     * @Bean:
     * 1: 这里声明该方法返回的是受Spring容器管理的Bean
     * 2: 方法名与返回类名一致,但首字母小写:为redisTemplateUser
     */
 
    @Bean
    public <T> RedisTemplate<String, T> 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;
    }
}

这个时候启动 SpringBoot 应用,Spring 的容器里面就管理着一个 name 为 redisTemplateUser 的 Bean 了,也就是通过这个 Bean 可以使用第二个数据源的 Redis。

最后我们做一个单元测试,创建一个测试类:RedisTest.java :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.demo.redisdemo.redis;
 
 
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
 
import java.util.concurrent.TimeUnit;
 
@SpringBootTest
public class RedisTest {
 
    /**
     * 当一个接口有多个实现类的时候
     * 将 @Qualifier 注解与我们想要使用的 Spring Bean 名称一起进行装配
     * Spring 框架就能从多个相同类型并满足装配要求的 Bean 中找到我们想要的
     *
     * 这里绑定初始化里面注入的Bean:redisTemplateUser
     */
 
    /**
     * 第二个数据源的配置并指定String数据类型 UserRedis
     */
    @Autowired
    @Qualifier("redisTemplateUser")
    private RedisTemplate<String, String> redisTemplateUser;
 
    /**
     * 默认数据源配置并指定String数据类型的Redis
     */
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
 
    /**
     * 默认数据源配置的String数据类型的Redis
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
     
 
    @Test
    public void redisTest() {
        System.out.println("----------Start----------");
 
        // 端口6380的Redis
        redisTemplateUser.opsForValue().set("redisTemplateUser", "success", 1, TimeUnit.DAYS);
 
        // 端口6379默认Redis
        redisTemplate.opsForValue().set("redisTemplate", "success", 1, TimeUnit.DAYS);
 
        // 端口6379并指定String数据类型的默认Redis
        stringRedisTemplate.opsForValue().set("stringRedisTemplate", "success", 1, TimeUnit.DAYS);
 
        System.out.println("----------End----------");
 
    }
}

最后开启两个 Redis,当前无数据:

 运行测试用例后,再查看 Redis 的缓存情况:

整个过程比较简单,就是引入扩展包,配置多数据源,读取数据源,初始化 Bean,最后就可以直接使用了。需要注意的是:因为 Redis 有默认的实现类了,所以在装配使用的时候,要加上 @Qualifier 注解并指定前面 Bean 注入的名字,不然自动注入后会使用默认的配置,不能使用指定的 Redis 数据源。

 

本篇代码 Github:https://github.com/Journeyerr/cnblogs/tree/master/redisDemo

Redis 扩展包https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis

线程池扩展包:https://mvnrepository.com/artifact/org.apache.commons/commons-pool2

  


__EOF__

  • 本文作者: 安逺
  • 本文链接: https://www.cnblogs.com/anyuan/p/15235102.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。