Java教程

Java SpringBoot配置Redis多数据源

本文主要是介绍Java SpringBoot配置Redis多数据源,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

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

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

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

<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;连接池的配置写在上面和下面都行,初始化的时候能读取到就行了

spring:
  redis:
    host: localhost
    port: 6379
    timeout: 3000
    database: 0

  # 第二个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 : 

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 :

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 :

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

  

这篇关于Java SpringBoot配置Redis多数据源的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!