Site icon Vinsguru

Redis Master Slave With Spring Boot

Overview:

In this tutorial, I would like to demo Redis Master Slave (Read Replicas) using docker compose for local development purposes for a Spring Boot application.

If you are new to Spring Boot Redis – check the below articles first.

Redis Master Slave:

Redis is an extremely fast in-memory DB and it is great for caching frequently accessed data for an application. Most of the applications have read heavy operations which involves complex queries with multiple tables joins. So it makes perfect sense to cache such information in redis when it is not going to change every time. Even though it helps with application performance, It might add load on a single redis instance when all the instances of app-servers keep on sending read and write requests to redis.

We can scale redis horizontally. We can run multiple instances of Redis with master slave architecture where master would be the write node and slaves would act as read-only nodes. Any updates to the master would be automatically synced with slave nodes asynchronously. Any write attempt to the slave nodes would be declined.

Redis Master Slave – Setup:

################################# REPLICATION #################################

# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
#   +------------------+      +---------------+
#   |      Master      | ---> |    Replica    |
#   | (receive writes) |      |  (exact copy) |
#   +------------------+      +---------------+
#
# 1) Redis replication is asynchronous, but you can configure a master to
#    stop accepting writes if it appears to be not connected with at least
#    a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the
#    master if the replication link is lost for a relatively small amount of
#    time. You may want to configure the replication backlog size (see the next
#    sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
#    network partition replicas automatically try to reconnect to masters
#    and resynchronize with them.
#
# replicaof <masterip> <masterport>
replicaof master 6379
version: '3'
services:
  master:
    container_name: master
    image: redis
    ports:
      - 6379:6379
  slave-1:
    container_name: slave-1
    image: redis
    ports:
      - 16379:6379
    volumes:
      - ./conf:/usr/local/etc/redis/
    command: redis-server /usr/local/etc/redis/redis.conf
  slave-2:
    container_name: slave-2
    image: redis
    ports:
      - 26379:6379
    volumes:
      - ./conf:/usr/local/etc/redis/
    command: redis-server /usr/local/etc/redis/redis.conf    
  redis-commander:
    container_name: redis-commander
    hostname: redis-commander
    image: rediscommander/redis-commander:latest
    restart: always
    environment:
    - REDIS_HOSTS=master:master,slave-1:slave-1,slave-2:slave-2
    ports:
    - "8081:8081"

Redis Commander – UI:

 

Redis Master Slave With Spring Boot:

Lets create a simple Spring Boot application to see how we can use the Redis cluster with master-slaves.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
redis:
  master:
    host: localhost
    port: 6379
  slaves:
    - host: localhost
      port: 16379
    - host: localhost
      port: 26379
@Configuration
@ConfigurationProperties(prefix = "redis")
public class RedisConfiguration {

    private RedisInstance master;
    private List<RedisInstance> slaves;

    RedisInstance getMaster() {
        return master;
    }

    void setMaster(RedisInstance master) {
        this.master = master;
    }

    List<RedisInstance> getSlaves() {
        return slaves;
    }

    void setSlaves(List<RedisInstance> slaves) {
        this.slaves = slaves;
    }

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
                .readFrom(ReadFrom.REPLICA_PREFERRED)
                .build();
        RedisStaticMasterReplicaConfiguration staticMasterReplicaConfiguration = new RedisStaticMasterReplicaConfiguration(this.getMaster().getHost(), this.getMaster().getPort());
        this.getSlaves().forEach(slave -> staticMasterReplicaConfiguration.addNode(slave.getHost(), slave.getPort()));
        return new LettuceConnectionFactory(staticMasterReplicaConfiguration, clientConfig);
    }

    private static class RedisInstance {

        private String host;
        private int port;

        String getHost() {
            return host;
        }

        void setHost(String host) {
            this.host = host;
        }

        int getPort() {
            return port;
        }

        void setPort(int port) {
            this.port = port;
        }
    }

}
@RestController
public class RedisController {

    private static final String KEY = "VINSGURU";

    @Autowired
    private StringRedisTemplate template;

    @GetMapping("/{name}")
    public void addToSet(@PathVariable String name) {
        this.template.opsForSet().add(KEY, name);
    }

    @GetMapping("/get")
    public Set<String> getKeyValues() {
        return this.template.opsForSet().members(KEY);
    }

}
http://localhost:8080/a
http://localhost:8080/b
http://localhost:8080/c

http://localhost:8080/get

# HTTP Response
["c","b","a"]

# Try to add new item. It will hang as master is down

http://localhost:8080/d


# Try to access existing items. It will give proper response as we read from read only nodes

http://localhost:8080/get

Summary:

Redis Master Slave setup is very easy. The redis replication is also very fast. I did a performance test to add 10000 keys into Redis master with 10 concurrent users using JMeter. I am able to see all the 10000 keys in the slave nodes almost immediately.

Read more about Redis.

This project is available here.

 

Share This:

Exit mobile version