Spring工程中集成多个redis数据源的思路详解

 更新时间:2025年07月28日 09:26:13   作者:亚林瓜子  
Spring项目集成双Redis数据源需配置两个连接工厂与RedisTemplate,通过@Primary指定默认Bean,@Qualifier注入特定Bean,支持集群环境,本文给大家介绍Spring工程中集成多个redis数据源的相关知识,感兴趣的朋友一起看看吧

问题

有个项目需要在同一个Spring工程中集成2个redis数据源。

思路

配置2个redis连接工厂,再配置2个redistemplate。然后,在使用缓存的时候,分别注入不同的redistemplate解决这个问题。这里主要是使用了spring中的2个注释:

  • @Primary:设置默认bean
  • @Qualifier:指定注入bean

解决

FhRedisConfig.java

这个类是配置第2个多余的redis,对application.yml文件中自定义redis配置映射类。如果application.yml文件中有如下配置:

fh:
	redis:
		host: 12.86.12.9
		password: swdghop
		port: 6379
		database:7

这对应配置类如下:

package com.xxxx.framework.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
 * redis配置类
 */
@Data
@ConfigurationProperties(prefix = "fh.redis")
public class FhRedisConfig {
    /**
     * 主机地址
     */
    private String host;
    /**
     * 密码
     */
    private String password;
    /**
     * Redis 服务器端口号
     * 默认值:6379(Redis 默认端口)
     */
    private int port = 6381;
    /**
     * Redis 数据库索引(0-15)
     * 默认值:0
     */
    private int database = 0;
}

RedisConfig.java

这是redis配置类,这里主要配置2个redis连接工厂,2个redistemplate的bean。而且,使用@Primary设置redistemplate类注入的默认bean为哪个redistemplate的bean。而且,如果增加了对redis集群配置的支持。

package com.xxxx.framework.config;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;
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.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
/**
 * redis配置
 * 
 */
@Configuration
@EnableCaching
@EnableConfigurationProperties(FhRedisConfig.class)
public class RedisConfig extends CachingConfigurerSupport
{
    @Resource
    private FhRedisConfig fhRedisConfig;
    @Value("${spring.profiles.active:default}")
    private String activeProfile;
    /**
     * 默认redis连接池
     * @return 默认redis连接池
     */
    @Bean
    @Primary
    public RedisConnectionFactory redisConnectionFactory(RedisProperties redisProperties) {
        // 从 RedisProperties 提取连接池配置(如果存在)
        return getRedisConnectionFactory(redisProperties, redisProperties.getHost(), redisProperties.getPort(), redisProperties.getPassword(),
                redisProperties.getDatabase(), redisProperties.getCluster() == null ? null : redisProperties.getCluster().getNodes());
    }
    /**
     * redis连接池
     * @return redis连接池
     */
    @Bean
    public RedisConnectionFactory fhRedisConnectionFactory(RedisProperties redisProperties) {
        return getRedisConnectionFactory(redisProperties, fhRedisConfig.getHost(), fhRedisConfig.getPort(), fhRedisConfig.getPassword(),
                fhRedisConfig.getDatabase(), null);
    }
    /**
     * redis客户端
     * @param connectionFactory redis连接池
     * @return redis客户端
     */
    @Bean
    public RedisTemplate<Object, Object> fhRedisTemplate(@Qualifier("fhRedisConnectionFactory")RedisConnectionFactory connectionFactory)
    {
        return getRedisTemplate(connectionFactory);
    }
    /**
     * 默认redis客户端
     * @param connectionFactory 默认redis连接池
     * @return 默认redis客户端
     */
    @Bean
    @Primary
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
    {
        return getRedisTemplate(connectionFactory);
    }
    private static RedisTemplate<Object, Object> getRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        FastJson2JsonRedisSerializer<Object> serializer = new FastJson2JsonRedisSerializer<>(Object.class);
        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        // Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }
    private RedisConnectionFactory getRedisConnectionFactory(RedisProperties redisProperties, String host, int port, String password, int database, List<String> nodes) {
        LettuceConnectionFactory lettuceConnectionFactory;
        // 根据是否是集群模式选择不同的配置
        if (!CollectionUtils.isEmpty(nodes)) {
            // 配置集群拓扑刷新选项
            ClusterTopologyRefreshOptions refreshOptions = ClusterTopologyRefreshOptions.builder()
                    .refreshPeriod(redisProperties.getLettuce().getCluster().getRefresh().getPeriod())
                    .enableAdaptiveRefreshTrigger(
                            ClusterTopologyRefreshOptions.RefreshTrigger.MOVED_REDIRECT,
                            ClusterTopologyRefreshOptions.RefreshTrigger.PERSISTENT_RECONNECTS)
                    .build();
            ClusterClientOptions clientOptions = ClusterClientOptions.builder()
                    .topologyRefreshOptions(refreshOptions)
                    .build();
            GenericObjectPoolConfig<?> poolConfig = getGenericObjectPoolConfig(redisProperties);
            LettucePoolingClientConfiguration.LettucePoolingSslClientConfigurationBuilder lettucePoolingSslClientConfigurationBuilder = LettucePoolingClientConfiguration.builder()
                    .clientOptions(clientOptions)
                    .poolConfig(poolConfig)  // 关键:设置连接池
                    .commandTimeout(redisProperties.getTimeout())
                    .useSsl();
            if (!activeProfile.equals("prod")) {
                lettucePoolingSslClientConfigurationBuilder.disablePeerVerification();
            }
            LettucePoolingClientConfiguration poolingClientConfig = lettucePoolingSslClientConfigurationBuilder.build();
            // 创建集群配置
            RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(nodes);
            clusterConfig.setPassword(password);
            // 创建 LettuceConnectionFactory
            lettuceConnectionFactory = new LettuceConnectionFactory(clusterConfig, poolingClientConfig);
        } else {
            // 非集群模式保持原逻辑
            GenericObjectPoolConfig<?> poolConfig = getGenericObjectPoolConfig(redisProperties);
            LettucePoolingClientConfiguration.LettucePoolingSslClientConfigurationBuilder lettucePoolingSslClientConfigurationBuilder = LettucePoolingClientConfiguration.builder()
                    .poolConfig(poolConfig)  // 关键:设置连接池
                    .commandTimeout(redisProperties.getTimeout())
                    .useSsl();
            if (!activeProfile.equals("prod")) {
                lettucePoolingSslClientConfigurationBuilder.disablePeerVerification();
            }
            RedisStaticMasterReplicaConfiguration serverConfig = new RedisStaticMasterReplicaConfiguration(host, port);
            serverConfig.setPassword(password);
            LettucePoolingClientConfiguration poolingClientConfig = lettucePoolingSslClientConfigurationBuilder.build();
            lettuceConnectionFactory = new LettuceConnectionFactory(serverConfig, poolingClientConfig);
        }
        lettuceConnectionFactory.setDatabase(database);
        return lettuceConnectionFactory;
    }
    private static GenericObjectPoolConfig<?> getGenericObjectPoolConfig(RedisProperties redisProperties) {
        GenericObjectPoolConfig<?> poolConfig = new GenericObjectPoolConfig<>();
        if (redisProperties.getLettuce().getPool() != null) {
            RedisProperties.Pool poolProps = redisProperties.getLettuce().getPool();
            poolConfig.setMaxTotal(poolProps.getMaxActive());      // max-active
            poolConfig.setMaxIdle(poolProps.getMaxIdle());        // max-idle
            poolConfig.setMinIdle(poolProps.getMinIdle());        // min-idle
            poolConfig.setMaxWaitMillis(poolProps.getMaxWait().toMillis());        // max-wait
        }
        return poolConfig;
    }
}

注意@Qualifier注释的使用,这里使用指定了特定的redis连接工厂。下面的在业务代码中注入redistemaplte的时候,也需要使用呢@Qualifier注释来使用特定的redis集群。

Controller.java

这是业务代码中,注入使用特定的redis集群,如下代码:

@Resource
@Qualifier("fhRedisTemplate")
private RedisTemplate<String, Integer> fhRedisTemplate;

如果不需要使用特定redis,只需要使用默认redis则不需要@Qualifier注释,如下:

@Resource
public RedisTemplate redisTemplate;

总结

这就是Spring项目redis多数据源问题。主要就是通过@Primary注释来配置默认bean,通过@Qualifier注释来指定使用的bean。

参考

到此这篇关于Spring工程中集成多个redis数据源的思路详解的文章就介绍到这了,更多相关Spring多个redis数据源内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java多线程编程之使用Synchronized块同步变量

    java多线程编程之使用Synchronized块同步变量

    我们可以通过synchronized块来同步特定的静态或非静态方法。要想实现这种需求必须为这些特性的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传入synchronized块
    2014-01-01
  • 浅析Java虚拟机详解之概述、对象生存法则

    浅析Java虚拟机详解之概述、对象生存法则

    这篇文章主要介绍了Java虚拟机详解之概述、对象生存法则,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • java自定注解完整示例代码

    java自定注解完整示例代码

    Java注解是一种元数据,可以提供有关程序代码的额外信息,它们可以用于标记类、方法、字段等元素,它允许我们在源代码中嵌入元数据这篇文章主要介绍了java自定注解的相关资料,需要的朋友可以参考下
    2026-01-01
  • 浅谈Java中的四种引用方式的区别

    浅谈Java中的四种引用方式的区别

    下面小编就为大家带来一篇浅谈Java中的四种引用方式的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • JAVA最容易忽视的数据类型之枚举详解

    JAVA最容易忽视的数据类型之枚举详解

    这篇文章主要给大家介绍了关于JAVA最容易忽视的数据类型之枚举的相关资料,Java中的枚举类型是一种特殊的类型,它允许程序员定义一个固定的值集合,并为每个值分配一个名称,枚举类型提供了一种简单、安全和可读性强的方式来表示一组相关的常量,需要的朋友可以参考下
    2023-10-10
  • 深入浅析Java 抽象类和接口

    深入浅析Java 抽象类和接口

    这篇文章主要介绍了Java 抽象类和接口的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • Java TreeSet类的简单理解和使用

    Java TreeSet类的简单理解和使用

    这篇文章主要介绍了Java TreeSet类的简单理解和使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • springboot 自定义权限标签(tld),在freemarker引用操作

    springboot 自定义权限标签(tld),在freemarker引用操作

    这篇文章主要介绍了springboot 自定义权限标签(tld),在freemarker引用操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • java  工厂方法详解及实例代码

    java 工厂方法详解及实例代码

    这篇文章主要介绍了java 工厂方法详解及实例代码的相关资料,需要的朋友可以参考下
    2017-01-01
  • Java中接口的多态详解

    Java中接口的多态详解

    大家好,本篇文章主要讲的是Java中接口的多态详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02

最新评论