springboot 同时连接多个redis

线上服务需要连接三个redis服务器;业务背景不能介绍,直接上代码:

技术选型:

Springboot连接reids的三个客户端:

Jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持,复杂的redis操作需要使用它;springboot1.x 默认集成;据说在高并发下有并发性问题出现;

Lettuce高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器,springboot 2.x 默认集成

Redission:Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。暂时企业级开发感觉只是使用了分布式锁

结论:

单个redis随便使用哪个客户端都可以,也可以使用 Jedis + Redission 或者 Lettuce + Redission;

由于Jedis使用和研究比较多,此处使用Jedis抛砖引玉,实现三组redis + 分布式锁;Lettuce版本也可以根据此思路编写;

代码部分:

maven pom引用:

        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
			<exclusions>
				<!-- 不依赖Redis的异步客户端lettuce -->
				<exclusion>
					<groupId>io.lettuce</groupId>
					<artifactId>lettuce-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
		</dependency>

application.yml配置

spring:
  redis:
    r1:
      host: 192.168.1.210
      port: 6379
      password: 
      #cluster:
        #nodes: 192.168.1.101:6379,192.168.1.102:6379,192.168.1.103:6379
    r2:
      host: 192.168.1.211
      port: 6379
      password: 
      #cluster:
        #nodes: 192.168.1.104:6379,192.168.1.105:6379,192.168.1.106:6379
    r3:
      host: 192.168.1.212
      port: 6379
      password: 
      #cluster:
        #nodes: 192.168.1.107:6379,192.168.1.108:6379,192.168.1.109:6379

Configuration代码:


import java.util.HashSet;
import java.util.Set;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.JedisPoolConfig;

/**
 * redis配置 三个redis同时存在
 * @author douzi
 * @date  2021-12-2 09:00:00
 */
@Slf4j
@Configuration
public class RedisJedisConfig2 {
	// r1 redis 配置信息
    @Value("${spring.redis.r1.host:}")
    private String r1Host;
 
    @Value("${spring.redis.r1.port:}")
    private Integer r1Port;

    @Value("${spring.redis.r1.password:}")
    private String r1Password;
    
    @Value("${spring.redis.r1.cluster.nodes:}")
    private String r1Nodes;
 
    //r2 redis 配置信息
    @Value("${spring.redis.r2.host:}")
    private String r2Host;
 
    @Value("${spring.redis.r2.port:}")
    private Integer r2Port;
 
    @Value("${spring.redis.r2.password:}")
    private String r2Password;
    
    @Value("${spring.redis.r2.cluster.nodes:}")
    private String r2Nodes;
    
    //r3 redis 配置信息
    @Value("${spring.redis.r3.host:}")
    private String r3Host;
 
    @Value("${spring.redis.r3.port:}")
    private Integer r3Port;
 
    @Value("${spring.redis.r3.password:}")
    private String r3Password;
    
    @Value("${spring.redis.r3.cluster.nodes:}")
    private String r3Nodes;
 
    /**
     * connectionFactory 配置工厂
     */
    public RedisConnectionFactory connectionFactory(
    		RedisStandaloneConfiguration redisStandaloneConfiguration, 
    		RedisClusterConfiguration redisClusterConfiguration, 
    		JedisPoolConfig jedisPoolConfig) {
    	if (redisStandaloneConfiguration == null && redisClusterConfiguration == null) {
    		log.error("==============请添加redis配置================");
    		return null;
    	}
    	
        JedisConnectionFactory jedisConnectionFactory = null;
        
        if (redisStandaloneConfiguration != null) {
        	jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration);
        } else {
        	jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration, jedisPoolConfig);
        }
        jedisConnectionFactory.afterPropertiesSet();
        
        // 检查是否可用
        RedisConnection connection = null;
        try {
        	connection = jedisConnectionFactory.getConnection();
        	log.info("reids是否可用:" + !connection.isClosed());
        } catch(Exception e) {
        	log.error("reids不可用,请检查组件是否启动:",e);
        } finally {
        	connection.close();
        }
        
        return jedisConnectionFactory;
    }
 
    /**
     * poolConfig连接池配置 只有集群时使用 直接写死,不让外部配置了
     * @return
     */
    public JedisPoolConfig poolConfig() {
    	JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(200);
        config.setMaxIdle(50);
        config.setMinIdle(8);
        config.setMaxWaitMillis(10000);         // 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
        config.setTestOnBorrow(true);           // 在获取连接的时候检查有效性, 默认false
        config.setTestOnReturn(false);          // 调用returnObject方法时,是否进行有效检查
        config.setTestWhileIdle(true);          // Idle时进行连接扫描
        config.setTimeBetweenEvictionRunsMillis(30000);     // 表示idle object evitor两次扫描之间要sleep的毫秒数
        config.setNumTestsPerEvictionRun(10);               // 表示idle object evitor每次扫描的最多的对象数
        config.setMinEvictableIdleTimeMillis(60000);        // 表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
        return config;
    }
    
    /**
     * redisStandaloneConfiguration 单机版配置
     * @param host
     * @param port
     * @param password
     * @param index
     * @return
     */
    public RedisStandaloneConfiguration redisStandaloneConfiguration(String host, int port, String password, int index) {
    	RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(host, port);
    	
    	if (StrUtil.isNotBlank(password)) {
    		redisStandaloneConfiguration.setPassword(password);
        }
    	if (index != 0) {
    		redisStandaloneConfiguration.setDatabase(index);
        }
    	return redisStandaloneConfiguration;
    }
    
    /**
     * redisClusterConfiguration 集群配置
     * @param clusterNodes
     * @param password
     * @return
     */
    public RedisClusterConfiguration redisClusterConfiguration(String clusterNodes, String password) {
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        // Set<RedisNode> clusterNodes
        String[] serverArray = clusterNodes.split(",");
        Set<RedisNode> nodes = new HashSet<RedisNode>();
        for (String ipPort : serverArray) {
            String[] ipAndPort = ipPort.split(":");
            nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));
        }
        redisClusterConfiguration.setClusterNodes(nodes);
        redisClusterConfiguration.setMaxRedirects(6);
        if (StrUtil.isNotBlank(password)) {
        	redisClusterConfiguration.setPassword(RedisPassword.of(password));
        }
        return redisClusterConfiguration;
    }
 
    @Bean(name = "redisR1Template")
    public RedisTemplate<String, Object> redisR1Template() {
    	RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisStandaloneConfiguration redisStandaloneConfiguration = null;
        RedisClusterConfiguration redisClusterConfiguration = null;
        if (StrUtil.isNotBlank(r1Host) && StrUtil.isBlank(r1Nodes)) {
        	redisStandaloneConfiguration = redisStandaloneConfiguration(r1Host, r1Port, r1Password, 0);
        } else if (StrUtil.isNotBlank(r1Nodes)) {
        	redisClusterConfiguration = redisClusterConfiguration(r1Nodes, r1Password);
        }
        log.info("=========================R1 redis信息 开始===============================");
        template.setConnectionFactory(connectionFactory(redisStandaloneConfiguration, redisClusterConfiguration, poolConfig()));
        log.info("=========================R1 redis信息 结束===============================");
        return template;
    }
 
    @Bean(name = "redisR2Template")
    public RedisTemplate<String, Object> redisR2Template() {
    	RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisStandaloneConfiguration redisStandaloneConfiguration = null;
        RedisClusterConfiguration redisClusterConfiguration = null;
        if (StrUtil.isNotBlank(r2Host) && StrUtil.isBlank(r2Nodes)) {
        	redisStandaloneConfiguration = redisStandaloneConfiguration(r2Host, r2Port, r2Password, 0);
        } else if (StrUtil.isNotBlank(r2Nodes)) {
        	redisClusterConfiguration = redisClusterConfiguration(r2Nodes, r2Password);
        }
        log.info("=========================R2 redis信息 开始===============================");
        template.setConnectionFactory(connectionFactory(redisStandaloneConfiguration, redisClusterConfiguration, poolConfig()));
        log.info("=========================R2 redis信息 结束===============================");
        return template;
    }
    
    @Bean(name = "redisR3Template")
    public RedisTemplate<String, Object> redisR3Template() {
    	RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisStandaloneConfiguration redisStandaloneConfiguration = null;
        RedisClusterConfiguration redisClusterConfiguration = null;
        if (StrUtil.isNotBlank(r3Host) && StrUtil.isBlank(r3Nodes)) {
        	redisStandaloneConfiguration = redisStandaloneConfiguration(r3Host, r3Port, r3Password, 0);
        } else if (StrUtil.isNotBlank(r3Nodes)) {
        	redisClusterConfiguration = redisClusterConfiguration(r3Nodes, r3Password);
        }
        log.info("=========================R3 redis信息 开始===============================");
        template.setConnectionFactory(connectionFactory(redisStandaloneConfiguration, redisClusterConfiguration, poolConfig()));
        log.info("=========================R3 redis信息 结束===============================");
        return template;
    }
}

其中在connectionFactory方法中,添加了,自动检查redis是否连接成功的代码,在启动项目时即可判断是否连接成功。

启动失败日志:

启动成功日志:

类中使用:

@RestController
@RequestMapping("/redis")
public class TestRedisController {
	@Autowired
	RedisTemplate<String, Object> redisR1Template;
	@Autowired
	RedisTemplate<String, Object> redisR2Template;
	@Autowired
	RedisTemplate<String, Object> redisR3Template;
	
	@GetMapping("/cs")
	public String test() {
		redisR1Template.opsForValue().get("1");
		redisR2Template.opsForValue().get("1");
		redisR3Template.opsForValue().get("1");
		return "1";
	}
}

  • 10
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
多个线程频繁地使用Redis时,使用连接池可以提高应用程序的性能。下面是使用连接池集成Redis的步骤: 1. 在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.10.0</version> </dependency> ``` 2. 创建Redis连接池配置类。以下是一个示例: ```java @Configuration public class RedisPoolConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.password}") private String password; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.maxIdle}") private int maxIdle; @Value("${spring.redis.maxTotal}") private int maxTotal; @Value("${spring.redis.maxWaitMillis}") private long maxWaitMillis; @Bean public JedisPool jedisPool() { JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxIdle(maxIdle); poolConfig.setMaxTotal(maxTotal); poolConfig.setMaxWaitMillis(maxWaitMillis); JedisPool jedisPool = new JedisPool(poolConfig, host, port, timeout, password); return jedisPool; } } ``` 在上面的代码中,我们使用JedisPoolConfig来配置我们的连接池,并创建一个JedisPool bean。您可以根据实际情况调整连接池的最大空闲连接数,最大连接数和最长等待时间。 3. 在您的服务类或控制器类中使用Redis连接池。您可以使用@Autowired注解注入JedisPool bean,然后使用它来获取Jedis实例并执行Redis操作。以下是一个示例: ```java @Autowired private JedisPool jedisPool; public void setValue(String key, String value) { try (Jedis jedis = jedisPool.getResource()) { jedis.set(key, value); } } public String getValue(String key) { try (Jedis jedis = jedisPool.getResource()) { return jedis.get(key); } } ``` 在上面的代码中,我们使用了try-with-resources语句来确保在使用完Jedis实例后关闭连接。这可以确保连接池中的连接得到正确释放。 这就是使用连接池集成Redis的步骤。希望这可以帮助您提高您的应用程序性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

窦再兴

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值