Skip to content

How to connect to multiple redis server when using spring boot ?

Purpose

In this article , I will demo how to connect to multiple redis servers using spring boot. Just as following picture shows, if you don’t know how to setup two redis servers in your environment, you can refer to this post.

image-20210305165358100

Environment

  • Spring boot 2+
  • Jdk 8+
  • Redis

Prepare the test data in redis

I deployed two redis docker container bw-redis1 and bw-redis2, now I use command line to set some values in them:

(base) [root@local ~]# docker exec -it bw-redis1 redis-cli
127.0.0.1:6379> set k1 redis1
OK
127.0.0.1:6379> get k1
"redis1"
127.0.0.1:6379> exit
(base) [root@local ~]# docker exec -it bw-redis2 redis-cli
127.0.0.1:6379> set k1 redis2
OK
127.0.0.1:6379> get k1
"redis2"
127.0.0.1:6379> exit
(base) [root@local ~]#

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
│   │   └── resources
│   │   └── application.properties

The Pom

We use maven to define the dependencies, I excluded the default lettuce sdk, because it’s not stable. I’d rather use the jedis sdk instead.

pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.2</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>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>

The code

1. Config file

Here in the src/main/resources/application.properties, I defined two redis server configurations,

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. You should change them to your real configurations.

2. Property config classes

To read the above properties file into spring boot, we must define configuration classes:

  1. At first, we define a common class as the base class of redis configuration classes
src/main/java/com.bswen.sbmr/config/RedisCommonProperty.java
public class RedisCommonProperty {
private String host;
private int port;
private int database;
//getters setters
}
  1. Then, we define Redis1Property and Redis2Property class to denote the different redis configurations
src/main/java/com.bswen.sbmr/config/Redis1Property.java
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
public class Redis1Property extends RedisCommonProperty {
}

And this:

src/main/java/com.bswen.sbmr/config/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.

  1. Thirdly, we should define how to get the RedisTemplate and RedisConnectionFactory from above properties

For redis server1, we define Redis1Configuration:

src/main/java/com.bswen.sbmr/config/Redis1Configuration.java
@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());
return redisConnectionFactory;
}
@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);
return stringRedisTemplate;
}
}

To avoid the following error:

***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named 'redisTemplate' that could not be found.

We need to change Redis1Configuration to this:

src/main/java/com.bswen.sbmr/config/Redis1Configuration.java
@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());
return redisConnectionFactory;
}
@Bean(name = "redis1StringRedisTemplate")
public StringRedisTemplate userStringRedisTemplate(@Qualifier("redis1ConnectionFactory") RedisConnectionFactory cf) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(cf);
return stringRedisTemplate;
}
@Bean(name = "redis1RedisTemplate")
@Bean(name = {"redis1RedisTemplate","redisTemplate"})
public RedisTemplate userRedisTemplate(@Qualifier("redis1ConnectionFactory") RedisConnectionFactory cf) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(cf);
return stringRedisTemplate;
}
}

Because springboot2 needs a default bean named redisTemplate, so we reuse the redis1RedisTemplate bean, add a name redisTemplate to it.

For redis server2, we define Redis2Configuration:

src/main/java/com.bswen.sbmr/config/Redis2Configuration.java
@Configuration
public class Redis2Configuration {
@Autowired
private Redis2Property redis2Property;
@Bean(name = "redis2ConnectionFactory")
public RedisConnectionFactory roleRedisConnectionFactory() {
JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
redisConnectionFactory.setHostName(redis2Property.getHost());
redisConnectionFactory.setPort(redis2Property.getPort());
redisConnectionFactory.setDatabase(redis2Property.getDatabase());
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:

src/main/java/com.bswen.sbmr/service/MultiRedisTestRunner.java
@Component
public class MultiRedisTestRunner implements CommandLineRunner {
private final static Logger logger = LoggerFactory.getLogger(MultiRedisApplication.class);
@Autowired
@Qualifier("redis1StringRedisTemplate")
private StringRedisTemplate stringRedisTemplate;
@Autowired
@Qualifier("redis2StringRedisTemplate")
private StringRedisTemplate stringRedis2Template;
//@Override
public void run(String... strings) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
try {
testRedis1();
testRedis2();
}finally {
latch.await();
}
}
private void testRedis2() {
try {
for (int i = 1; i < 2; i++) {
logger.info("=====================================================================");
logger.info("start loop redis 2:" + i);
String key = "k" + i;
String primaryKeyValue = stringRedis2Template.opsForValue().get(key);
logger.info("=====================================================================");
logger.info(String.format("read from the redis2, key %s value is %s", key, primaryKeyValue));
}
}finally {
}
}
private void testRedis1() {
try {
for (int i = 1; i < 2; i++) {
logger.info("=====================================================================");
logger.info("start loop redis 1:" + i);
String key = "k" + i;
String primaryKeyValue = stringRedisTemplate.opsForValue().get(key);
logger.info("=====================================================================");
logger.info(String.format("read from the redis1, key %s value is %s", key, primaryKeyValue));
}
}finally {
}
}
}

Run it, we get this result:

Terminal window
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.2)
2024-12-30 18:05:56.099 WARN 49528 --- [ main] o.s.boot.StartupInfoLogger : InetAddress.getLocalHost().getHostName() took 5002 milliseconds to respond. Please verify your network configuration (macOS machines may need to add entries to /etc/hosts).
2024-12-30 18:06:01.116 INFO 49528 --- [ main] com.bswen.sbr2.MultiRedisApplication2 : Starting MultiRedisApplication2 using Java 1.8.0_341 on MacBook-Pro-zzz.local with PID 49528 (/Users/zzz/....../bswen-project/spring-boot-multiredis2/target/classes started by zzz in /Users/zzz/private/bw/bswen-github/bswen-project)
2024-12-30 18:06:01.117 INFO 49528 --- [ main] com.bswen.sbr2.MultiRedisApplication2 : No active profile set, falling back to default profiles: default
2024-12-30 18:06:01.509 INFO 49528 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2024-12-30 18:06:01.512 INFO 49528 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2024-12-30 18:06:01.533 INFO 49528 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 Redis repository interfaces.
2024-12-30 18:06:02.058 INFO 49528 --- [ main] com.bswen.sbr2.MultiRedisApplication2 : Started MultiRedisApplication2 in 21.403 seconds (JVM running for 21.935)
2024-12-30 18:06:02.060 INFO 49528 --- [ main] c.b.sbr2.service.MultiRedisTestRunner : =====================================================================
2024-12-30 18:06:02.060 INFO 49528 --- [ main] c.b.sbr2.service.MultiRedisTestRunner : start loop redis 1:1
2024-12-30 18:06:02.187 INFO 49528 --- [ main] c.b.sbr2.service.MultiRedisTestRunner : =====================================================================
2024-12-30 18:06:02.188 INFO 49528 --- [ main] c.b.sbr2.service.MultiRedisTestRunner : read from the redis1, key k1 value is redis1
2024-12-30 18:06:02.188 INFO 49528 --- [ main] c.b.sbr2.service.MultiRedisTestRunner : =====================================================================
2024-12-30 18:06:02.188 INFO 49528 --- [ main] c.b.sbr2.service.MultiRedisTestRunner : start loop redis 2:1
2024-12-30 18:06:03.286 INFO 49528 --- [ main] c.b.sbr2.service.MultiRedisTestRunner : =====================================================================
2024-12-30 18:06:03.287 INFO 49528 --- [ main] c.b.sbr2.service.MultiRedisTestRunner : read from the redis2, key k1 value is redis2

It works!

Summary

In this post, I demonstrated how to connect to multiple redis server instances with spring boot 2, the key point is that you should setup specific configuration for each redis server connection. Thanks for your reading. All code of the project is uploaded to github.com, you can download at this link.

Final Words + More Resources

My intention with this article was to help others who might be considering using multiple redis in one spring boot application. So I hope that’s been the case here. If you still have any questions, don’t hesitate to ask me by email: [email protected].

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

⭐️ Thanks For Your Support 🙏