背景
最近线上碰到一个多redis源的场景,一个工程需要整合两个redis。这时使用一些数据传输、转换工具,例如filebeat、logstash、kafka-connect等,这或许也是个不错的方法,但是因为历史原因,最后还是需要到工程里面自己整合。话不多说直接开整!
引入依赖
下面直接给出pom文件依赖配置:
<!-- springboot官方整合redis依赖, 版本根据自己常用springboot的版本来 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
<!-- fastjson依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.32</version>
</dependency>
<!-- 对象转换工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
添加Redis环境
application.yml添加redis配置:
spring:
# redis-1
redis:
database: 0
# redis服务器地址
host: 192.168.2.3
# Redis服务器连接端口
port: 6379
lettuce:
pool:
# 连接池最大连接数(使用负值表示没有限制) 默认 8
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
max-wait: -1
# 连接池中的最大空闲连接 默认 8
max-idle: 8
# 连接池中的最小空闲连接 默认 0
min-idle: 0
# redis服务器连接密码(默认为空)
password: 123456
timeout: 800
# redis-2
redis-live:
database: 0
host: 192.168.2.8
port: 6379
lettuce:
pool:
max-active: 8
max-wait: -1
max-idle: 8
min-idle: 0
password: 234567
timeout: 800
Redis配置
接下来编写redis配置类,在装配不同的RedisTemplate的时候根据需要采用不同的序列化方式,在使用的时候按需引入,下面是我的注入配置:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching
public class RedisTemplateConfig {
/**
* live数据源
*/
@Value("${spring.redis-live.host}")
private String redisLiveHost;
@Value("${spring.redis-live.port}")
private int redisLivePort;
@Value("${spring.redis-live.password}")
private String redisLivePass;
@Value("${spring.redis-live.database}")
private int redisLiveDb;
/**
* 公共配置
*/
@Value("${spring.redis.timeout}")
private long timeout;
@Value("${spring.redis.lettuce.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.lettuce.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.lettuce.pool.max-active}")
private int maxActive;
@Value("${spring.redis.lettuce.pool.max-wait}")
private int maxWait;
/**
* 装配 RedisTemplate
*/
// @Bean(name = "redisTemplate")
// public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// return createRedisTemplate(redisConnectionFactory);
// }
@Bean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
/**
* 装配 StringRedisTemplate
*/
@Bean(name = "stringRedisTemplate")
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return createStringRedisTemplate(redisConnectionFactory);
}
/**
* 装配 live数据源
*/
@Bean(name = "liveStringRedisTemplate")
public StringRedisTemplate liveStringRedisTemplate() {
return createStringRedisTemplate(redisLiveHost, redisLivePort, redisLivePass, redisLiveDb);
}
/**
* 创建 RedisTemplate
*/
public RedisTemplate<Object, Object> createRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
Jackson2JsonRedisSerializer<?> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
serializer.setObjectMapper(objectMapper);
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 创建 StringRedisTemplate
*/
public StringRedisTemplate createStringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
return stringRedisTemplate;
}
/**
* 创建 StringRedisTemplate
*/
public StringRedisTemplate createStringRedisTemplate(String host, int port, String password, int database) {
// 基本配置
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName(host);
configuration.setPort(port);
configuration.setDatabase(database);
if (ObjectUtils.isNotEmpty(password)) {
RedisPassword redisPassword = RedisPassword.of(password);
configuration.setPassword(redisPassword);
}
// 连接池通用配置
GenericObjectPoolConfig<?> genericObjectPoolConfig = new GenericObjectPoolConfig<>();
genericObjectPoolConfig.setMaxTotal(maxActive);
genericObjectPoolConfig.setMinIdle(minIdle);
genericObjectPoolConfig.setMaxIdle(maxIdle);
genericObjectPoolConfig.setMaxWaitMillis(maxWait);
// Lettuce Pool
LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
builder.poolConfig(genericObjectPoolConfig);
builder.commandTimeout(Duration.ofSeconds(timeout));
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(configuration, builder.build());
connectionFactory.afterPropertiesSet();
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(connectionFactory);
return stringRedisTemplate;
}
}
这里注意@Bean(name = "liveStringRedisTemplate")
将类交给spring,后面在引用会根据名称引入。
使用
在使用的时候我们使用@Qualifier显示引用对象:
// redis-1
@Autowired
@Qualifier("redisTemplate")
private RedisTemplate<String, String> redisTemplate;
// redis-2
@Autowired
@Qualifier("liveStringRedisTemplate")
private RedisTemplate<String, String> liveStringRedisTemplate;
下面我们可以使用RedisTemplate愉快地操作redis了!到这里springboot配置多数据源就成功了,这里的RedisTemplate还可以整合进工具类,让操作更加方便!