在集群环境的情况下连接多个Redis数据库是很正常的情况,因为平时都是使用本地环境的单Redis情况比较多,在这里用代码总结一下连接多个数据库的情况(主要是不同ip,同一个ip的不通数据库修改不通地方即可),这里还是使用的springboot提供的spring-boot-starter-data-redis工具包,具体介绍如下:
1.引入redis相关的jar
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies>
2.在配置文件application.properties文件中设置redis相关配置,这里我使用了一个本地的redis数据库,一个远程的redis数据库,这里只假设了ip地址不同,其他的配置都相同:
#配置缓存redis spring.redis.database=8 # Redis服务器地址 spring.redis.host=127.0.0.1 # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) spring.redis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.keytimeout=1000 spring.redis.timeout=0 #配置第二个redis数据库地址 spring.redis.host2=172.19.3.150
3.添加RedisTemplate的Bean:
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 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.jedis.JedisConnectionFactory; 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.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPoolConfig; /** * @author liaoyubo * @version 1.0 2017/8/1 * @description */ @Configuration public class RedisConfig { @Value("${spring.redis.host}") private String hostName; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.password}") private String passWord; @Value("${spring.redis.pool.max-idle}") private int maxIdl; @Value("${spring.redis.pool.min-idle}") private int minIdl; @Value("${spring.redis.database}") private int database; @Value("${spring.redis.keytimeout}") private long keytimeout; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.host2}") private String hostName2; /*@Bean public JedisConnectionFactory redisConnectionFactory() { JedisConnectionFactory factory = new JedisConnectionFactory(); factory.setHostName(hostName); factory.setPort(port); factory.setTimeout(timeout); //设置连接超时时间 return factory; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); setSerializer(template); //设置序列化工具,这样ReportBean不需要实现Serializable接口 template.afterPropertiesSet(); return template; } private void setSerializer(StringRedisTemplate template) { Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); }*/ @Bean public RedisConnectionFactory redisConnectionFactory(){ JedisPoolConfig poolConfig=new JedisPoolConfig(); poolConfig.setMaxIdle(maxIdl); poolConfig.setMinIdle(minIdl); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); poolConfig.setNumTestsPerEvictionRun(10); poolConfig.setTimeBetweenEvictionRunsMillis(60000); JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig); jedisConnectionFactory.setHostName(hostName); if(!passWord.isEmpty()){ jedisConnectionFactory.setPassword(passWord); } jedisConnectionFactory.setPort(port); jedisConnectionFactory.setDatabase(database); return jedisConnectionFactory; } @Bean public RedisConnectionFactory redisConnectionFactory2(){ JedisPoolConfig poolConfig=new JedisPoolConfig(); poolConfig.setMaxIdle(maxIdl); poolConfig.setMinIdle(minIdl); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); poolConfig.setNumTestsPerEvictionRun(10); poolConfig.setTimeBetweenEvictionRunsMillis(60000); JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig); jedisConnectionFactory.setHostName(hostName2); if(!passWord.isEmpty()){ jedisConnectionFactory.setPassword(passWord); } jedisConnectionFactory.setPort(port); jedisConnectionFactory.setDatabase(database); return jedisConnectionFactory; } @Bean(name = "redisTemplate1") public RedisTemplate<String, Object> redisTemplateObject() throws Exception { RedisTemplate<String, Object> redisTemplateObject = new RedisTemplate<String, Object>(); redisTemplateObject.setConnectionFactory(redisConnectionFactory()); setSerializer(redisTemplateObject); redisTemplateObject.afterPropertiesSet(); return redisTemplateObject; } @Bean(name = "redisTemplate2") public RedisTemplate<String, Object> redisTemplateObject2() throws Exception { RedisTemplate<String, Object> redisTemplateObject = new RedisTemplate<String, Object>(); redisTemplateObject.setConnectionFactory(redisConnectionFactory2()); setSerializer(redisTemplateObject); redisTemplateObject.afterPropertiesSet(); return redisTemplateObject; } private void setSerializer(RedisTemplate<String, Object> template) { Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>( Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setKeySerializer(template.getStringSerializer()); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); //在使用String的数据结构的时候使用这个来更改序列化方式 /*RedisSerializer<String> stringSerializer = new StringRedisSerializer(); template.setKeySerializer(stringSerializer ); template.setValueSerializer(stringSerializer ); template.setHashKeySerializer(stringSerializer ); template.setHashValueSerializer(stringSerializer );*/ } }
4.App启动类:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author liaoyubo * @version 1.0 2017/7/31 * @description */ @SpringBootApplication public class App { public static void main(String [] args){ SpringApplication.run(App.class); } }
5.测试多个Redis数据库连接:
import com.springRedis.App; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; /** * @author liaoyubo * @version 1.0 2017/7/31 * @description */ @RunWith(SpringRunner.class) @SpringBootTest(classes = App.class) public class PipelineTest { @Autowired @Resource(name = "redisTemplate1") private RedisTemplate<String,Object> redisTemplate1; @Autowired @Resource(name = "redisTemplate2") private RedisTemplate<String,Object> redisTemplate2; @Test public void testPipeLine(){ redisTemplate1.opsForValue().set("a",1); redisTemplate1.opsForValue().set("b",2); /*redisTemplate1.executePipelined(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection redisConnection) throws DataAccessException { redisConnection.openPipeline(); for (int i = 0;i < 10;i++){ redisConnection.incr("a".getBytes()); } System.out.println("a:"+redisTemplate1.opsForValue().get("a")); redisTemplate1.opsForValue().set("c",3); for(int j = 0;j < 20;j++){ redisConnection.incr("b".getBytes()); } System.out.println("b:"+redisTemplate1.opsForValue().get("b")); System.out.println("c:"+redisTemplate1.opsForValue().get("c")); redisConnection.closePipeline(); return null; } });*/ System.out.println("b:"+redisTemplate1.opsForValue().get("b")); System.out.println("a:"+redisTemplate1.opsForValue().get("a")); redisTemplate2.opsForValue().set("m",5); redisTemplate2.opsForValue().set("n",6); System.out.println("m:"+redisTemplate2.opsForValue().get("m")); System.out.println("n:"+redisTemplate2.opsForValue().get("n")); }
以上就是连接2个Redis数据库的例子,在这里还有一个需要注意的是不能将
private RedisTemplate<String,Object> redisTemplate1
代码中的redisTemplate1修改为redisTemplate,因为这个redisTemplate可能是程序中默认的全局变量,具体的代码逻辑没有去查看,如果修改为了redisTemplate的话会出现以下错误:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<?, ?>' available: expected single matching bean but found 2: redisTemplate1,redisTemplate2 at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ... 33 more
如果在设置RedisConnectionFactory的连接工厂时,一定要保留一个如下的代码:
public RedisConnectionFactory redisConnectionFactory()
否则会出现以下错误:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' available: expected single matching bean but found 2: redisConnectionFactory1,redisConnectionFactory2 at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ... 47 more
相关推荐
"通过RedisTemplate连接多个Redis过程解析" 本文主要介绍了通过RedisTemplate连接多个Redis过程解析,详细介绍了使用SpringBoot提供的spring-boot-starter-data-redis工具包连接多个Redis数据库的过程。 首先,在...
然后,我们创建一个RedisConfig配置类,初始化RedisTemplate: ```java @Configuration public class RedisConfig { @Bean public RedisConnectionFactory redisConnectionFactory() { ...
基于`SpringBoot2.X + Lettuce`实现Redis集成和多库实时切换是一个非常实用的项目。以下是对该项目的一些重点说明: 1. **项目概述** 该项目的主要目标是在`SpringBoot`...可以配置多个Redis实例,用于实现多库切换。
Redis集群采用分片(Sharding)策略来分布数据,将键空间划分为多个槽(Slots),每个节点负责一部分槽。当客户端对某个键进行操作时,会根据槽的映射规则确定操作的目标节点,从而实现负载均衡。 2. **Spring集成...
通过定义多个`DataSource`实例,每个实例对应一个数据源,然后创建一个`AbstractRoutingDataSource`子类,重写`determineCurrentLookupKey`方法来根据业务逻辑动态选择当前要使用的数据源。这样,我们就可以在代码中...
Redis是一个开源的、基于键值对的数据存储系统,常用于缓存、消息队列和数据持久化等多个场景。而Spring Boot是Spring框架的一个简化版,它提供了开箱即用的特性,使得构建微服务应用变得更为便捷。 首先,为了在...
然后,定义一个RedisTemplate bean,用于操作Redis。在Spring Boot自动配置的基础上,我们通常不需要手动创建这个bean,但可以根据需要自定义配置: ```java @Configuration public class RedisConfig { @Bean ...
这样,我们就能灵活地在多个Redis数据库之间切换,满足不同场景的需求。在实际开发中,还可以结合Spring的其他特性,如AOP(面向切面编程)来实现更复杂的逻辑,比如在特定的请求条件下自动切换数据库。
哨兵系统由多个哨兵节点组成,它们之间通过 gossip 协议交换信息,共同维护整个集群的健康状态。 配置哨兵模式主要包括以下几个步骤: 1. **启动哨兵节点**:在每个哨兵节点的配置文件中,需要指定要监视的主节点...
Redis Sentinel系统通常由多个Sentinel节点组成,它们共同监控主Redis服务器和其备份服务器(Slaves)。Sentinel节点之间通过Gossip协议进行通信,共享状态信息,并对主服务器的健康状况进行检查。当主服务器故障时...
6. **事务支持**: 虽然Redis本身不支持事务,但Spring Data Redis提供了一种模拟事务的机制,可以控制多个Redis操作的原子性。 通过以上步骤,你可以在Spring 3.0应用中成功集成Redis。需要注意的是,随着Spring和...
然后通过 `@Autowired` 注解注入 `StringRedisTemplate` 或 `RedisTemplate` 对象,这两个模板类提供了操作 Redis 的便捷方法。例如: ```yaml spring: redis: host: localhost port: 6379 ``` ```java @...
在实际应用中,如果需要更高级别的事务管理,比如跨多个键的操作,可能需要借助分布式事务解决方案,如Seata、TCC(Try-Confirm-Cancel)模式或者Saga模式。这些方案可以在微服务架构中提供分布式事务的支持,但实现...
Redis Cluster是Redis官方提供的分布式解决方案,它将数据分片到多个节点上,每个节点存储一部分数据,从而实现了水平扩展。Redis Cluster采用了无中心的设计,所有节点彼此通信,共同维护整个集群的状态。 ### 2. ...
3. **主从复制**:通过复制,Redis可以创建多个从节点来分担负载,提升读取性能,同时为主节点提供故障转移的备份。 4. **哨兵系统(Sentinel)**:Redis Sentinel是一个高可用性解决方案,它可以监控主从节点的...
在使用Redis进行数据操作时,我们可能需要事务支持,比如在多个操作之间保持原子性。Spring TX提供了一种声明式事务管理,使得在代码中无需显式控制事务边界,而是通过配置来实现。 5. **lettuce** Lettuce是另一...
`RedisTemplate`是Spring Data Redis提供的一个工具类,用于执行各种Redis操作。例如,我们可以通过`opsForValue()`方法进行键值对的操作,`opsForHash()`处理哈希表,`opsForSet()`处理集合等。 4. **Redis事务...
Redis Cluster通过将数据分割成多个槽(slots)并分布在多个节点之间来实现数据的分布式存储,每个节点负责一部分槽,从而达到水平扩展的目的。 **Spring与Redis的整合** Spring框架提供了一套完善的集成Redis的...
* 集群模式:将多个 Redis 服务器组成一个集群,以提高系统的可扩展性和高可用性。 七、结论 本文档详细讲解了如何搭建 Spring Boot 与 Redis 集群的关联操作,包括搭建 Redis 集群、Spring Boot 配置调用 Redis、...
【Redis与Spring集成】 Redis,一个高性能的键值对存储系统,常被用作数据库、缓存和消息中间件。其高效性能得益于内存存储和...不过,随着Spring Data Redis的更新,建议考虑使用更新的版本以获得更多的特性和改进。