Spring工程中集成多個redis數(shù)據(jù)源的思路詳解
問題
有個項目需要在同一個Spring工程中集成2個redis數(shù)據(jù)源。
思路
配置2個redis連接工廠,再配置2個redistemplate。然后,在使用緩存的時候,分別注入不同的redistemplate解決這個問題。這里主要是使用了spring中的2個注釋:
@Primary:設(shè)置默認(rèn)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
這對應(yīng)配置類如下:
package com.xxxx.framework.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* redis配置類
*/
@Data
@ConfigurationProperties(prefix = "fh.redis")
public class FhRedisConfig {
/**
* 主機(jī)地址
*/
private String host;
/**
* 密碼
*/
private String password;
/**
* Redis 服務(wù)器端口號
* 默認(rèn)值:6379(Redis 默認(rèn)端口)
*/
private int port = 6381;
/**
* Redis 數(shù)據(jù)庫索引(0-15)
* 默認(rèn)值:0
*/
private int database = 0;
}RedisConfig.java
這是redis配置類,這里主要配置2個redis連接工廠,2個redistemplate的bean。而且,使用@Primary設(shè)置redistemplate類注入的默認(rèn)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;
/**
* 默認(rèn)redis連接池
* @return 默認(rèn)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);
}
/**
* 默認(rèn)redis客戶端
* @param connectionFactory 默認(rèn)redis連接池
* @return 默認(rèn)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;
// 根據(jù)是否是集群模式選擇不同的配置
if (!CollectionUtils.isEmpty(nodes)) {
// 配置集群拓?fù)渌⑿逻x項
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) // 關(guān)鍵:設(shè)置連接池
.commandTimeout(redisProperties.getTimeout())
.useSsl();
if (!activeProfile.equals("prod")) {
lettucePoolingSslClientConfigurationBuilder.disablePeerVerification();
}
LettucePoolingClientConfiguration poolingClientConfig = lettucePoolingSslClientConfigurationBuilder.build();
// 創(chuàng)建集群配置
RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(nodes);
clusterConfig.setPassword(password);
// 創(chuàng)建 LettuceConnectionFactory
lettuceConnectionFactory = new LettuceConnectionFactory(clusterConfig, poolingClientConfig);
} else {
// 非集群模式保持原邏輯
GenericObjectPoolConfig<?> poolConfig = getGenericObjectPoolConfig(redisProperties);
LettucePoolingClientConfiguration.LettucePoolingSslClientConfigurationBuilder lettucePoolingSslClientConfigurationBuilder = LettucePoolingClientConfiguration.builder()
.poolConfig(poolConfig) // 關(guān)鍵:設(shè)置連接池
.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連接工廠。下面的在業(yè)務(wù)代碼中注入redistemaplte的時候,也需要使用呢@Qualifier注釋來使用特定的redis集群。
Controller.java
這是業(yè)務(wù)代碼中,注入使用特定的redis集群,如下代碼:
@Resource
@Qualifier("fhRedisTemplate")
private RedisTemplate<String, Integer> fhRedisTemplate;如果不需要使用特定redis,只需要使用默認(rèn)redis則不需要@Qualifier注釋,如下:
@Resource public RedisTemplate redisTemplate;
總結(jié)
這就是Spring項目redis多數(shù)據(jù)源問題。主要就是通過@Primary注釋來配置默認(rèn)bean,通過@Qualifier注釋來指定使用的bean。
參考
- Multiple Redis Connections in Spring Boot
- Spring Boot Redis CRUD Example
- The Spring @Qualifier Annotation
- Connection Modes
- 【Redis】Integration with Spring Boot
- Accessing AWS ElastiCache (Redis) from different Amazon VPC(s) via AWS PrivateLink
到此這篇關(guān)于Spring工程中集成多個redis數(shù)據(jù)源的思路詳解的文章就介紹到這了,更多相關(guān)Spring多個redis數(shù)據(jù)源內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文詳解Java17中LinkedList類的用法和應(yīng)用場景
LinkedList 是 Java 集合框架中基于雙向鏈表實現(xiàn)的類,實現(xiàn)了 List 和 Deque 接口,本文將為大家介紹一下它在Java 17 中如何更高效的使用吧2025-03-03

