springboot-配置多redis数据源

22 篇文章 0 订阅
1 篇文章 0 订阅

       实际工作中,redis实例可能不止一个,而是多个,所以在一些项目工程中需要配置多个redis数据源,如果采用jedis、jediscluster、shardedjedis的话就不存在配置了,可以多个实例即可,在这主要说明的是springboot+redistemplate+rediscluster的配置使用。

1、首先,pom文件提供下,方便查看相关包的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.zh.redis</groupId>
	<artifactId>zh-redis-operation</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>zh-redis-operation</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
			<version>2.3.3.RELEASE</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
			<version>2.8.1</version>
		</dependency>


		<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.8</version>
			<scope>provided</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.10</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.73</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

2、提供下yml配置文件,IP、PORT就简写了

server:
  port: 9030
  servlet:
    context-path: /template
spring:
  news:
    cluster:
      nodes: ip:port,ip:port ...
      max-redirects: 2
    password: 123456
    lettuce:
      pool:
        max-active: 10
        max-idle: 8
        max-wait: -1ms
        min-idle: 0
  svideo:
    cluster:
      nodes: ip:port,ip:port ...
      max-redirects: 2
    password: 123456
    lettuce:
      pool:
        max-active: 10
        max-idle: 8
        max-wait: -1ms
        min-idle: 0

3、接下来主要说明下核心配置代码RedisClusterProperties、SpringBootRedisConfig

package com.zh.redis.config.redis;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author : Lu Ma Ren
 * @Date: 2020-09-10 15:16
 * @Description: V-
 */
@SuppressWarnings("all")
@Setter
@Getter
@Component
public class RedisClusterProperties {

    @Value("${spring.news.password}")
    private String newsPassword;
    @Value("${spring.news.cluster.nodes}")
    private String newsNodes;
    @Value("${spring.news.cluster.max-redirects}")
    private int newsMaxRedirects;

    @Value("${spring.svideo.password}")
    private String svideoPassword;
    @Value("${spring.svideo.cluster.nodes}")
    private String svideoNodes;
    @Value("${spring.svideo.cluster.max-redirects}")
    private int svideoMaxRedirects;
}
package com.zh.redis.config.redis;

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.RedisNode;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
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.StringRedisSerializer;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : Lu Ma Ren
 * @Date: 2020-09-10 14:48
 * @Description: V-
 */
@SuppressWarnings("all")
@Slf4j
@Configuration
public class SpringBootRedisConfig {

    @Autowired
    private RedisClusterProperties redisClusterProperties;

    @Bean("newsConfig")
    @ConfigurationProperties(prefix = "spring.news.lettuce.pool")
    @Primary
    public GenericObjectPoolConfig newsConfig() {
        return new GenericObjectPoolConfig<>();
    }

    @Bean("svideoConfig")
    @ConfigurationProperties(prefix = "spring.svideo.lettuce.pool")
    public GenericObjectPoolConfig svideoConfig() {
        return new GenericObjectPoolConfig<>();
    }

    @Bean("newsClusterConfiguration")
    @ConfigurationProperties(prefix = "spring.news.cluster")
    @Primary
    public RedisClusterConfiguration newsClusterConfiguration() {
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        redisClusterConfiguration.setMaxRedirects(redisClusterProperties.getNewsMaxRedirects());
        List<RedisNode> nodeList = new ArrayList<>();
        String[] cNodes = redisClusterProperties.getNewsNodes().split(",");
        for (String node : cNodes) {
            String[] hp = node.split(":");
            nodeList.add(new RedisNode(hp[0], Integer.parseInt(hp[1])));
        }
        redisClusterConfiguration.setClusterNodes(nodeList);
        redisClusterConfiguration.setPassword(redisClusterProperties.getNewsPassword());
        return redisClusterConfiguration;
    }

    @Bean("svideoClusterConfiguration")
    @ConfigurationProperties(prefix = "spring.svideo.cluster")
    public RedisClusterConfiguration svideoClusterConfiguration() {
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        redisClusterConfiguration.setMaxRedirects(redisClusterProperties.getSvideoMaxRedirects());
        List<RedisNode> nodeList = new ArrayList<>();
        String[] cNodes = redisClusterProperties.getSvideoNodes().split(",");
        for (String node : cNodes) {
            String[] hp = node.split(":");
            nodeList.add(new RedisNode(hp[0], Integer.parseInt(hp[1])));
        }
        redisClusterConfiguration.setClusterNodes(nodeList);
        redisClusterConfiguration.setPassword(redisClusterProperties.getSvideoPassword());
        return redisClusterConfiguration;
    }

    @Bean("newsLettuceConnectionFactory")
    @Primary
    public LettuceConnectionFactory factory(@Qualifier("newsConfig") GenericObjectPoolConfig newsConfig,
                                            @Qualifier("newsClusterConfiguration") RedisClusterConfiguration newsClusterConfiguration) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(newsConfig).build();
        return new LettuceConnectionFactory(newsClusterConfiguration, clientConfiguration);
    }

    @Bean("svideoLettuceConnectionFactory")
    public LettuceConnectionFactory factory2(@Qualifier("svideoConfig") GenericObjectPoolConfig svideoConfig,
                                             @Qualifier("svideoClusterConfiguration") RedisClusterConfiguration svideoClusterConfiguration) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(svideoConfig).build();
        return new LettuceConnectionFactory(svideoClusterConfiguration, clientConfiguration);
    }

    /**
     * RedisTemplate 数据存入redis,需要配置序列化
     */
    @Bean("newsRedisTemplate")
    @Primary
    public RedisTemplate<String, Object> newsRedisTemplate(@Qualifier("newsLettuceConnectionFactory") LettuceConnectionFactory newsLettuceConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(newsLettuceConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new FastJsonRedisSerializer<>(Object.class));
        redisTemplate.setValueSerializer(new FastJsonRedisSerializer<>(Object.class));
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * RedisTemplate 数据存入redis,需要配置序列化
     */
    @Bean("svideoRedisTemplate")
    public RedisTemplate<String, Object> svideoRedisTemplate(@Qualifier("svideoLettuceConnectionFactory") LettuceConnectionFactory svideoLettuceConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(svideoLettuceConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new FastJsonRedisSerializer<>(Object.class));
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new FastJsonRedisSerializer<>(Object.class));
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean("newsStringRedisTemplate")
    @Primary
    public StringRedisTemplate newsStringRedisTemplate(@Qualifier("newsLettuceConnectionFactory") LettuceConnectionFactory newsLettuceConnectionFactory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(newsLettuceConnectionFactory);
        stringRedisTemplate.afterPropertiesSet();
        return stringRedisTemplate;
    }

    @Bean("svideoStringRedisTemplate")
    public StringRedisTemplate svideoStringRedisTemplate(@Qualifier("svideoLettuceConnectionFactory") LettuceConnectionFactory svideoLettuceConnectionFactory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(svideoLettuceConnectionFactory);
        stringRedisTemplate.afterPropertiesSet();
        return stringRedisTemplate;
    }
}

我这边就展示了两个数据源的配置,以及RedisTemplate、StringRedisTemplate的配置。

4、接下来展示使用

    @Autowired
    @Qualifier("newsRedisTemplate")
    private RedisTemplate newsRedisTemplate;

    @Autowired
    @Qualifier("svideoRedisTemplate")
    private RedisTemplate svideoRedisTemplate;

    @Autowired
    @Qualifier("newsStringRedisTemplate")
    private StringRedisTemplate newsStringRedisTemplate;

    @Autowired
    @Qualifier("svideoStringRedisTemplate")
    private StringRedisTemplate svideoStringRedisTemplate;

对应的使用,就可以在代码中调用rediscluster了

 

总结:

1、RedisTemplate、StringRedisTemplate

StringRedisTemplate其实是继承自RedisTemplate,采用了RedisSerializer.string()进行序列化的,有疑惑的可以查看下源码,在结合SpringBootRedisConfig配置文件最后几个方法对比,就可以明白这俩的区别。

2、Autowired+Qualifier  还有Resources

Autowired和Resources,这俩的区别就是类型注入还是名称注入的问题,有兴趣度娘一堆说明,比我说的好,这块使用完全看个人习惯了,我个人倾向于Autowired+Qualifier,虽然代码多但是看着清晰

3、集群、哨兵的配置上的区别

这块的话,其实整体流程是一样的,只不过在进行配置连接工厂的时候,注入的对象不同,源码已经很明确了,在源码LettuceConnectionFactory类中,对于new LettuceConnectionFactory() 时候,有几种不同的参数,大约在代码150行上下。源代码如下:

    public LettuceConnectionFactory(RedisStandaloneConfiguration standaloneConfig, LettuceClientConfiguration clientConfig) {
        this(clientConfig);
        Assert.notNull(standaloneConfig, "RedisStandaloneConfiguration must not be null!");
        this.standaloneConfig = standaloneConfig;
        this.configuration = this.standaloneConfig;
    }

    public LettuceConnectionFactory(RedisConfiguration redisConfiguration, LettuceClientConfiguration clientConfig) {
        this(clientConfig);
        Assert.notNull(redisConfiguration, "RedisConfiguration must not be null!");
        this.configuration = redisConfiguration;
    }

    public LettuceConnectionFactory(RedisSentinelConfiguration sentinelConfiguration, LettuceClientConfiguration clientConfig) {
        this(clientConfig);
        Assert.notNull(sentinelConfiguration, "RedisSentinelConfiguration must not be null!");
        this.configuration = sentinelConfiguration;
    }

    public LettuceConnectionFactory(RedisClusterConfiguration clusterConfiguration, LettuceClientConfiguration clientConfig) {
        this(clientConfig);
        Assert.notNull(clusterConfiguration, "RedisClusterConfiguration must not be null!");
        this.configuration = clusterConfiguration;
    }

4、采用原生连接

采用jedis等原生连接技术也是可以的,没有这么多复杂的文件,这个好坏不做评价,感觉跟个人习惯有关吧,我这个的业务系统采用的原生连接,因为我的业务系统需要连接redis个数不下30,有集群、单机、哨兵。千万别问为啥配置这么多,项目历史原因加上改造成本所以你懂得。

 

一点一点积累,总有收获的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值