springboot-how to connect to multiple redis server when using spring boot 1.x ?
Purpose
In this article , I would demo how to connect to multiple(for example 2) redis server using spring boot app. Just as following picture shows, if you don’t know how to start two redis server in your system, you can refer to this post.
Environment
- Spring boot 1.x
- Jdk 8
- Redis
The Project Layout
The layout of this demo project is as follows, all the example code can be found here:
➜ spring-boot-multiredis git:(master) tree .
.
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── bswen
│ │ │ └── sbmr
│ │ │ ├── MultiRedisApplication.java
│ │ │ ├── config
│ │ │ │ ├── Redis1Configuration.java
│ │ │ │ ├── Redis1Property.java
│ │ │ │ ├── Redis2Configuration.java
│ │ │ │ ├── Redis2Property.java
│ │ │ │ └── RedisCommonProperty.java
│ │ │ └── service
│ │ │ ├── MultiRedisTestRunner.java
│ │ │ └── MyMessageReceiver.java
│ │ └── resources
│ │ └── application.properties
The Pom
We use maven to define the dependencies:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<start-class>Application</start-class>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<artifactId>spring-boot-multiredis</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
The code
1. Config file: src/main/resources/application.properties
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0
spring.redis2.host=localhost
spring.redis2.port=26379
spring.redis2.database=0
Here we define two redis connection, one is localhost:6379, the other is localhost:26379
2. Property config classes: src/main/java/com.bswen.sbmr/config/
To read the above properties file into spring boot, we must define configuration classes:
At first, we define a common class as the base class of redis configuration classes:
public class RedisCommonProperty {
private String host;
private int port;
private int database;
//getters setters
}
Then, we define Redis1Property and Redis2Property class to denote the different redis configurations
Redis1Property.java
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
public class Redis1Property extends RedisCommonProperty {
}
Redis2Property.java
@Configuration
@ConfigurationProperties(prefix = "spring.redis2")
public class Redis2Property extends RedisCommonProperty {
}
Pay attention to the ConfigurationProperties annotation, we use it to load different properties from the application.properties file.
Thirdly, we should define how to get the RedisTemplate and RedisConnectionFactory from above properties:
For redis server1, we define Redis1Configuration:
@Configuration
public class Redis1Configuration {
@Autowired
private Redis1Property redis1Property;
@Primary
@Bean(name = "redis1ConnectionFactory")
public RedisConnectionFactory userRedisConnectionFactory() {
JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
redisConnectionFactory.setHostName(redis1Property.getHost());
redisConnectionFactory.setPort(redis1Property.getPort());
redisConnectionFactory.setDatabase(redis1Property.getDatabase());
redisConnectionFactory.setPoolConfig(getPoolConfig());
return redisConnectionFactory;
}
private JedisPoolConfig getPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(8);
jedisPoolConfig.setMinIdle(1);
jedisPoolConfig.setMaxTotal(8);
return jedisPoolConfig;
}
@Bean(name = "redis1StringRedisTemplate")
public StringRedisTemplate userStringRedisTemplate(@Qualifier("redis1ConnectionFactory") RedisConnectionFactory cf) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(cf);
return stringRedisTemplate;
}
@Bean(name = "redis1RedisTemplate")
public RedisTemplate userRedisTemplate(@Qualifier("redis1ConnectionFactory") RedisConnectionFactory cf) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(cf);
//setSerializer(stringRedisTemplate);
return stringRedisTemplate;
}
}
For redis server2, we define Redis2Configuration:
@Configuration
public class Redis2Configuration {
@Autowired
private Redis2Property redis2Property;
private JedisPoolConfig getPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(8);
jedisPoolConfig.setMinIdle(1);
jedisPoolConfig.setMaxTotal(8);
return jedisPoolConfig;
}
@Bean(name = "redis2ConnectionFactory")
public RedisConnectionFactory roleRedisConnectionFactory() {
JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
redisConnectionFactory.setHostName(redis2Property.getHost());
redisConnectionFactory.setPort(redis2Property.getPort());
redisConnectionFactory.setDatabase(redis2Property.getDatabase());
redisConnectionFactory.setPoolConfig(getPoolConfig());
return redisConnectionFactory;
}
@Bean(name = "redis2StringRedisTemplate")
public StringRedisTemplate roleStringRedisTemplate(@Qualifier("redis2ConnectionFactory") RedisConnectionFactory cf) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(cf);
return stringRedisTemplate;
}
@Bean(name = "redis2RedisTemplate")
public RedisTemplate roleRedisTemplate(@Qualifier("redis2ConnectionFactory") RedisConnectionFactory cf) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(cf);
//setSerializer(stringRedisTemplate);
return stringRedisTemplate;
}
}
Now we have setup the properties and the configurations , we have beans of RedisTemplate , we can test it as follows:
@Component
public class MultiRedisTestRunner implements CommandLineRunner {
private final static Logger logger = LoggerFactory.getLogger(MultiRedisApplication.class);
@Autowired
@Qualifier("redis1StringRedisTemplate")
private StringRedisTemplate userStringRedisTemplate;
@Autowired
@Qualifier("redis2StringRedisTemplate")
private StringRedisTemplate roleStringRedisTemplate;
@Override
public void run(String... strings) throws Exception {
try {
for (int i = 0; i < 10; i++) {
logger.info("=====================================================================");
logger.info("start loop " + i);
String key = "key" + i;
userStringRedisTemplate.opsForValue().set(key, "value" + i);
roleStringRedisTemplate.opsForValue().set(key, "value" + (i + 1));
String primaryKeyValue = userStringRedisTemplate.opsForValue().get(key);
String secondaryKeyValue = roleStringRedisTemplate.opsForValue().get(key);
logger.info("=====================================================================");
logger.info(String.format("read from the redis1, key %s value is %s", key, primaryKeyValue));
logger.info(String.format("read from the redis2, key %s value is %s", key, secondaryKeyValue));
}
}catch(Exception ex) {
throw ex;
}
}
}
Run it, we get this result:
3-05 17:26:49.352 INFO 13130 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647
2021-03-05 17:26:49.481 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.482 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 0
2021-03-05 17:26:49.507 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.507 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key0 value is value0
2021-03-05 17:26:49.507 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key0 value is value1
2021-03-05 17:26:49.507 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.507 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 1
2021-03-05 17:26:49.511 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.511 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key1 value is value1
2021-03-05 17:26:49.511 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key1 value is value2
2021-03-05 17:26:49.511 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.512 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 2
2021-03-05 17:26:49.515 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.516 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key2 value is value2
2021-03-05 17:26:49.516 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key2 value is value3
2021-03-05 17:26:49.516 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.516 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 3
2021-03-05 17:26:49.520 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.520 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key3 value is value3
2021-03-05 17:26:49.520 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key3 value is value4
2021-03-05 17:26:49.520 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.520 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 4
2021-03-05 17:26:49.524 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.524 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key4 value is value4
2021-03-05 17:26:49.524 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key4 value is value5
2021-03-05 17:26:49.524 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.524 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 5
2021-03-05 17:26:49.528 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.529 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key5 value is value5
2021-03-05 17:26:49.529 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key5 value is value6
2021-03-05 17:26:49.529 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.529 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 6
2021-03-05 17:26:49.533 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.533 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key6 value is value6
2021-03-05 17:26:49.533 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key6 value is value7
2021-03-05 17:26:49.533 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.533 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 7
2021-03-05 17:26:49.538 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.538 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key7 value is value7
2021-03-05 17:26:49.538 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key7 value is value8
2021-03-05 17:26:49.538 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.538 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 8
2021-03-05 17:26:49.542 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.542 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key8 value is value8
2021-03-05 17:26:49.542 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key8 value is value9
2021-03-05 17:26:49.542 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.542 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : start loop 9
2021-03-05 17:26:49.546 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : =====================================================================
2021-03-05 17:26:49.546 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis1, key key9 value is value9
2021-03-05 17:26:49.546 INFO 13130 --- [ main] com.bswen.sbmr.MultiRedisApplication : read from the redis2, key key9 value is value10
It works!
By the way: How to subscribe to two redis server simultaneously?
Now we can connect two redis server , send command (get/set/…) to them and get response, but how can we use the pub/sub functions to listen to redis channels?
As the above picture shown, the process is as follows:
- You should have two redis server running
- Your spring boot application connects to the two redis servers
- Then you can subscribe to topics on the two redis servers by using spring boot RedisMessageListener
- At last, the messages would be forwarded to a RedisReceiver to process
So the key point is how to setup two redis servers’ RedisMessageListener, let’s check the code:
@Component
public class MultiRedisListenerTester {
@Bean
RedisMessageListenerContainer container1(@Qualifier("redis1ConnectionFactory") RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("tasks1"));
return container;
}
@Bean
RedisMessageListenerContainer container2(@Qualifier("redis2ConnectionFactory") RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("tasks2"));
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(MyMessageReceiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
}
Let’s analyze the above code:
- We create a class named MultiRedisListenerTester with the annotation @Component, which indicate that the class is a spring bean.
- The method named container1 and container2 has two parameters, one is connectionFactory, which is injected with specified redisConnectionFactory with @Qualifer annotation, the redisConnectionFactory beans are defined in Redis1Configuration and Redis2Configuration, the other is a listenerAdapter, which is supplied by listenerAdapter method defined below.
- We subscribed with topic name tasks1 on redis server1 and tasks2 on redis server2.
- The method named listenerAdapter indicates that when redis get a message, it would push the message the the receiver’s receiveMessage method.
Now let’s check the reciever’s code:
@Component
public class MyMessageReceiver {
private static Log log = LogFactory.getLog(MyMessageReceiver.class);
public void receiveMessage(String message) {
log.info("got message "+message);
}
}
Let test the multiple redis server’s pub/sub feature on redis server1:
//publish on redis server1 with redis-cli console
localhost-6379:0>publish tasks1 hello1
1
//got message from spring boot message receiver:
2021-03-06 11:22:31.465 INFO 17414 --- [ container1-2] c.bswen.sbmr.service.MyMessageReceiver : got message hello1
Let test the multiple redis server’s pub/sub feature on redis server2:
//publish on redis server2 with redis-cli console
localhost-6379:0>publish tasks2 hello2
1
//got message from spring boot message receiver:
2021-03-06 11:22:32.465 INFO 17414 --- [ container1-2] c.bswen.sbmr.service.MyMessageReceiver : got message hello2
If you want to tell from which redis server pushed the message, e.g. the source of the message, you can inject different named MessageListenerAdapter instances by using @Qualifier injection in method container1 and container2.
For example:
@Bean
RedisMessageListenerContainer container2(@Qualifier("redis2ConnectionFactory") RedisConnectionFactory connectionFactory,
@Qualifier("redis2Listener") MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("tasks2"));
return container;
}
@Bean(name="redis2Listener")
MessageListenerAdapter listenerAdapter(MyMessageReceiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
Summary
In this post, I demonstrated how to connect to multiple redis server instances with spring boot, the key point is that you should setup specific configuration for each redis server connection. And I also showed how to use the pub/sub function of springboot in the multiple redis server environment, thanks for your reading. All code of the project is uploaded to github.com, you can download at this link.