需求:springboot集成多数据源redis,其中有哨兵模式redis,也有集群redis
说明:1、如果只需要单哨兵redis或者单集群redis集成的话,则只需要加一个spring-boot-starter-data-redis依赖,配置文件只需要哨兵的或者集群的,并且不需要config类,使用的时候用默认的redisTemplate和StringRedisTemplate就行了。(网上很多这种列子)
2、如果只需要多数据源集群redis的话,需要spring-boot-starter-data-redis和commons-pool2依赖,配置文件即是我下面的集群这种配置,然后只需要RedisClusterSourceConfig来config,使用用RedisNewService和RedisNewServiceImpl就行了。(网上也有参考列子)
3、如果只需要多数据源哨兵edis的话,没有去实现,猜测:需要spring-boot-starter-data-redis和jedis依赖,配置文件即是我下面的集群这种配置,然后只需要RedisSentinelSourceConfig来config,增加对应的工厂和redistemplate实例即可(注:未实现,感兴趣的同学可以试试)
实现方式:jedis来实现哨兵模式的redis+lettuce来实现多数据源集群redis
首先pom.xml增加必要的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
配置文件,application-dev.properties
#redis 哨兵模式 缓存配置项
spring.redis.sentinel.nodes=
#master
spring.redis.sentinel.master=
#登录密码
spring.redis.password=
#spring.redis.password=ENC(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
#最大连接数
spring.redis.maxTotal=100
#最大空闲连接数
spring.redis.maxIdle=50
#最小空闲连接数
spring.redis.minIdle=30
##获取连接最大等待时间 ms
spring.redis.maxWaitMillis=10000
#redis操作的超时时间
spring.redis.timeout=10000
#集群模式 多数据源
#默认redis
spring.redis1.cluster.max-redirects=3
spring.redis1.cluster.nodes=
spring.redis1.password=
spring.redis1.database=0
spring.redis1.timeout=6000
spring.redis1.lettuce.pool.max-active=1000
spring.redis1.lettuce.pool.max-wait=-1
spring.redis1.lettuce.pool.max-idle=10
spring.redis1.lettuce.pool.min-idle=5
#redis2
spring.redis2.cluster.max-redirects=3
spring.redis2.cluster.nodes=
spring.redis2.password=
config类:
RedisClusterSourceConfig.java和RedisSentinelSourceConfig.java
代码块:
@Configuration
public class RedisClusterSourceConfig {
@Autowired
private Environment environment;
/**
* 配置lettuce连接池
*
* @return
*/
@SuppressWarnings("rawtypes")
@Bean
@ConfigurationProperties(prefix = "spring.redis1.lettuce.pool")
public GenericObjectPoolConfig redisPool() {
return new GenericObjectPoolConfig();
}
/**
* 配置第一个数据源的
*
* @return
*/
@Bean("redisClusterConfig")
@Primary
public RedisClusterConfiguration redisClusterConfig() {
Map<String, Object> source = new HashMap<>(8);
source.put("spring.redis.cluster.nodes",environment.getProperty("spring.redis1.cluster.nodes"));
RedisClusterConfiguration redisClusterConfiguration;
redisClusterConfiguration = new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source));
redisClusterConfiguration.setPassword(environment.getProperty("spring.redis1.password"));
return redisClusterConfiguration;
}
/**
* 配置第一个数据源的连接工厂
* 这里注意:需要添加@Primary 指定bean的名称,目的是为了创建两个不同名称的LettuceConnectionFactory
*
* @param redisPool
* @param redisClusterConfig
* @return
*/
@SuppressWarnings("rawtypes")
@Bean("factory1")
@Primary
public LettuceConnectionFactory lettuceConnectionFactory(GenericObjectPoolConfig redisPool, @Qualifier("redisClusterConfig") RedisClusterConfiguration redisClusterConfig) {
LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(redisPool).build();
return new LettuceConnectionFactory(redisClusterConfig, clientConfiguration);
}
/**
* 配置第一个数据源的RedisTemplate
* 注意:这里指定使用名称=factory1 的 RedisConnectionFactory
* 并且标识第一个数据源是默认数据源 @Primary
*
* @param redisConnectionFactory
* @return
*/
@SuppressWarnings("rawtypes")
@Bean("redisTemplate1")
@Primary
public RedisTemplate redisTemplate(@Qualifier("factory1") RedisConnectionFactory redisConnectionFactory) {
return getRedisTemplate(redisConnectionFactory);
}
/**
* 配置第二个数据源
*
* @return
*/
@Bean("secondaryRedisClusterConfig")
public RedisClusterConfiguration secondaryRedisConfig() {
Map<String, Object> source = new HashMap<>(8);
source.put("spring.redis.cluster.nodes", environment.getProperty("spring.redis2.cluster.nodes"));
RedisClusterConfiguration redisClusterConfiguration;
redisClusterConfiguration = new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source));
redisClusterConfiguration.setPassword(environment.getProperty("spring.redis2.password"));
return redisClusterConfiguration;
}
@SuppressWarnings("rawtypes")
@Bean("factory2")
public LettuceConnectionFactory secondaryLettuceConnectionFactory(GenericObjectPoolConfig redisPool, @Qualifier("secondaryRedisClusterConfig")RedisClusterConfiguration secondaryRedisClusterConfig) {
LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(redisPool).build();
return new LettuceConnectionFactory(secondaryRedisClusterConfig, clientConfiguration);
}
/**
* 配置第二个数据源的RedisTemplate
* 注意:这里指定使用名称=factory2 的 RedisConnectionFactory
*
* @param redisConnectionFactory
* @return
*/
@SuppressWarnings("rawtypes")
@Bean("redisTemplate2")
public RedisTemplate secondaryRedisTemplate(@Qualifier("factory2") RedisConnectionFactory redisConnectionFactory) {
return getRedisTemplate(redisConnectionFactory);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private RedisTemplate getRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
@Configuration
public class RedisSentinelSourceConfig {
@Autowired
private Environment environment;
@Bean("jedisSentinelPool")
@ConfigurationProperties(prefix="spring.redis")
public JedisPoolConfig getRedisConfig(){
JedisPoolConfig config = new JedisPoolConfig();
return config;
}
@Bean("redisSentinelConfig")
public RedisSentinelConfiguration redisSentinelConfig() {
RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration();
redisSentinelConfiguration.setMaster(environment.getProperty("spring.redis.sentinel.master"));
String[] sens = environment.getProperty("spring.redis.sentinel.nodes").split(",");
for (int i = 0; i < sens.length; i++) {
String[] str = sens[i].split(":");
RedisNode redisServer = new RedisServer(str[0], Integer.parseInt(str[1]));
redisSentinelConfiguration.sentinel(redisServer);
}
return redisSentinelConfiguration;
}
@SuppressWarnings("deprecation")
@Bean("jedisSentinelFactory")
public JedisConnectionFactory jedisConnectionFactory(@Qualifier("jedisSentinelPool")JedisPoolConfig jedisPoolConfig,@Qualifier("redisSentinelConfig")RedisSentinelConfiguration sentinelConfig) {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(sentinelConfig,jedisPoolConfig);
jedisConnectionFactory.setPassword(environment.getProperty("spring.redis.password"));
return jedisConnectionFactory;
}
@Bean("stringRedisTemplate3")
public StringRedisTemplate stringRedisTemplate(@Qualifier("jedisSentinelFactory")JedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
//自定义序列化方式
stringRedisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
stringRedisTemplate.setKeySerializer(stringRedisSerializer);
stringRedisTemplate.setHashKeySerializer(stringRedisSerializer);
return stringRedisTemplate;
}
@Bean("redisTemplate3")
public RedisTemplate<String,Object> redisTemplate(@Qualifier("jedisSentinelFactory")JedisConnectionFactory redisConnectionFactory){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
return redisTemplate;
}
}
具体的使用:
主要代码段:
@Autowired
@Qualifier("redisTemplate1")
private RedisTemplate<String,Object> firstRedisTemplate;
@Autowired
@Qualifier("redisTemplate2")
private RedisTemplate<String,Object> secondRedisTemplate;
@Override
public String get(String key, String num) {
if (StringUtils.isEmpty(key)) {
return null;
}
if("1".equals(num)) {
String value = (String) firstRedisTemplate.opsForValue().get(key);
return value;
}else if("2".equals(num)) {
String value = (String) secondRedisTemplate.opsForValue().get(key);
return value;
}
return null;
}
@Autowired
@Qualifier("stringRedisTemplate3")
private StringRedisTemplate stringRedisTemplate;
@SuppressWarnings("rawtypes")
@Autowired
@Qualifier("redisTemplate3")
private RedisTemplate redisTemplate;
@Override
public String get(String key) {
if (StringUtils.isEmpty(key)) {
// logger.warn("get redis Cache by key: null.");
return null;
}
return stringRedisTemplate.opsForValue().get(key);
}
@SuppressWarnings("unchecked")
@Override
public void set(byte[] key, byte[] value) {
if (StringUtils.isEmpty(key)) {
// logger.warn("set redis Cache by key: null.");
return;
}
ValueOperations<byte[], byte[]> valueOps = redisTemplate.opsForValue();
valueOps.set(key, value);
}
如果大家有更好的实现方式,请留言给我,互相交流。
只是作为一个开发记录。