Backend/Redis

센티널 로컬과 도커에 적용해보기

olsohee 2024. 5. 31. 00:53

로컬에 적용

이전 글에서 레디스의 복제와 센티널에 대해 알아봤다. 이번 글에서는 이들을 로컬 환경과 도커 환경에서 직접 적용해보자. 우선 로컬에 적용해보자.

 

레디스 서버는 다음과 같다.

  • 마스터: 6379 포트
  • 슬레이브: 6380 포트

그리고 레디스 센티널 서버는 다음과 같다.

  • 센티널 서버 1: 26379 포트
  • 센티널 서버 2: 26380 포트
  • 센티널 서버 3: 26381 포트

레디스 서버 띄우기(복제 환경)

우선 복제 환경을 구성하기 위해 레디스 마스터와 슬레이브 서버를 띄워보자.

 

/etc/redis 경로에 다음 두 개의 파일을 만들어뒀다.

  • sudo nano /etc/redis/master.conf
  • sudo nano /etc/redis/slave.conf

master.conf

port 6379
masterauth 1234
requirepass 1234

 

slave.conf

port 6380            
replicaof 127.0.0.1 6379                      
masterauth 1234      
requirepass 1234

 

  • port: 포트를 지정한다.
  • replicaof <마스터 ip> <마스터 port>: 복제할 마스터 노드의 ip 주소와 포트를 지정한다.
  • masterauth: 해당 서버가 마스터 서버에 접근할 때 필요한 비밀번호이다.
  • requirepass: 클라이언트가 해당 서버에 접근할 때 필요한 비밀번호이다.

그리고 설정 파일을 통해 두 개의 레디스 서버를 띄우면 된다.

  • sudo redis-server /etc/redis/master.conf
  • sudo redis-server /etc/redis/slave.conf

센티널 서버 띄우기

센티널 서버의 설정 파일도 /etc/redis 경로에 위치하며 그 내용은 다음과 같다.

 

sentinel-26379.conf

port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster 1234

 

sentinel-26380.conf

port 26380
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster 1234

 

sentinel-26381.conf

port 26381
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster 1234

 

  • sentinel monitor <마스터 이름> <마스터 ip> <마스터 port> <쿼럼 수>: 센티널이 감시할 마스터를 지정하며 마스터 이름을 붙여준다. 그리고 마지막 숫자는 쿼럼 수를 의미한다.
  • sentinel auth-pass <마스터 이름> <감시하는 레디스의 패스워드>: 패스워드가 걸려 있는 레디스를 모니터링할 경우에는 해당 명령어를 통해 패스워드를 지정해야 한다.

그리고 설정 파일을 이용해 센티널 서버를 띄우면 된다.

  • sudo redis-sentinel /etc/redis/sentinel-26379.conf
  • sudo redis-sentinel /etc/redis/sentinel-26380.conf
  • sudo redis-sentinel /etc/redis/sentinel-26381.conf

스프링 연동

스프링에서 레디스 센티널을 사용하려면 다음과 같이 설정하면 된다. (참고: https://docs.spring.io/spring-data/redis/reference/redis/connection-modes.html#redis:sentinel)

  • new RedisSentinelConfiguration().master("mymaster"): 앞서 센티널 설정 파일에서 sentinel monitor mymaster 127.0.0.1 6379 2 를 통해 감시할 마스터 노드의 이름을 mymaster라고 지정해줬다. 따라서 스프링 설정 코드에서도 와 같이 지정해줘야 한다.
  • sentinelConfiguration.setPassword("1234"): 레디스 서버는 1234라는 비밀번호를 가진다. 따라서 앞서 센티널 설정 파일에서 sentinel auth-pass mymaster 1234 를 통해 감시할 레디스 서버의 비밀번호를 입력해줬는데, 스프링 설정 코드에서도 감시할 레디스 서버에 접근하기 위해 비밀번호를 입력해야 한다.
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.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

@Configuration
public class RedisConfig {

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {

        RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration()
                .master("mymaster")
                .sentinel("localhost", 26379)
                .sentinel("localhost", 26380)
                .sentinel("localhost", 26381);
                
        sentinelConfiguration.setPassword("1234");
        
        return new LettuceConnectionFactory(sentinelConfiguration);
    }
}

테스트

6379, 6380 둘 다 실행 상태

스프링 서버를 띄우고 레디스에 접근을 필요로 하는 api를 호출해봤다. 그리고 다음과 같이 성공적으로 수행되었다.

 

레디스 서버를 확인해보자. 레디스 cli에 접속하기 위해선 redis-cli -p 포트번호 를 사용하면 되고, 비밀번호가 설정된 레디스 서버에 접속한 후에는 auth 비밀번호 를 입력하면 된다. 결과는 다음과 같다.

  • 6379: 자신이 마스터이며, 6380이 자신의 슬레이브이다.
  • 6380: 자신이 슬레이브이며, 6379가 자신의 마스터이다.
  • 센티널: 마스터인 6379를 감시하고 있다.

6379 shutdown

이번에는 마스터 서버인 6379 서버를 shutdown 명령어를 통해 꺼보자. 결과는 다음과 같다.

  • 6380: 마스터가 되었으며, 자신의 슬레이브는 없다.
  • 센티널: 새로운 마스터인 6380을 감시한다.

 

참고로 이때 레디스에 접근을 필요로 하는 api를 호출하면, 6380으로 연결되어 데이터 삽입/조회 모두 정상 동작한다.

6379 재시작

이번에는 6379 포트를 통해 레디스 서버를 재시작해보자. 그리고 이전처럼 레디스 서버를 띄울 때 master.conf 설정 파일을 사용했다. (sudo redis-server /etc/redis/master.conf)

  • 6379: master.conf 파일을 사용했음에도 슬레이브이며, 6380이 자신의 마스터이다.
  • 6380: 여전히 마스터이며 자신의 슬레이브로 6379가 추가되었다.
  • 센티널: 여전히 마스터인 6380을 감시한다.

도커에 적용

도커 컴포즈 파일

마스터 서버와 슬레이브 서버, 그리고 3개의 센티널 서버를 도커에 띄우기 위해 도커 컴포즈 파일을 사용했다.

 

컴포즈 파일은 다음과 같다.

services:
  redis-master:
    image: bitnami/redis
    container_name: redis-master
    hostname: redis-master
    environment:
      - REDIS_REPLICATION_MODE=master
      - REDIS_PASSWORD=1234 # 해당 레디스 서버 접속을 위한 패스워드
      - REDIS_MASTER_PASSWORD=1234 # 마스터 서버 접속을 위한 패스워드
    ports:
      - "6379:6379"
    networks:
      - funfit

  redis-slave:
    image: bitnami/redis
    container_name: redis-slave
    hostname: redis-slave
    environment:
      - REDIS_REPLICATION_MODE=slave
      - REDIS_MASTER_HOST=redis-master
      - REDIS_PASSWORD=1234
      - REDIS_MASTER_PASSWORD=1234
    ports:
      - "6380:6379"
    depends_on:
      - redis-master
    networks:
      - funfit

  redis-sentinel-1:
    image: bitnami/redis-sentinel
    container_name: redis-sentinel-1
    hostname: redis-sentinel-1
    environment:
      - REDIS_MASTER_HOST=redis-master # 감시할 호스트 이름 (위에서 hostname으로 지정한 값)
      - REDIS_MASTER_SET=mymaster # 마스터 이름 지정
      - REDIS_MASTER_PASSWORD=1234 # 감시할 마스터 서버에 접근하기 위한 비밀번호
      - REDIS_SENTINEL_QUORUM=2 # 쿼럼 수
    depends_on:
      - redis-master
      - redis-slave
    ports:
      - "26379:26379"
    networks:
      - funfit

  redis-sentinel-2:
    image: bitnami/redis-sentinel
    container_name: redis-sentinel-2
    hostname: redis-sentinel-2
    environment:
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_SET=mymaster
      - REDIS_MASTER_PASSWORD=1234
      - REDIS_SENTINEL_QUORUM=2
    depends_on:
      - redis-master
      - redis-slave
    ports:
      - "26380:26379"
    networks:
      - funfit

  redis-sentinel-3:
    image: bitnami/redis-sentinel
    container_name: redis-sentinel-3
    hostname: redis-sentinel-3
    environment:
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_SET=mymaster
      - REDIS_MASTER_PASSWORD=1234
      - REDIS_SENTINEL_QUORUM=2
    depends_on:
      - redis-master
      - redis-slave
    ports:
      - "26381:26379"
    networks:
      - funfit

networks:
  funfit:
    external: true

 

참고로 만약 레디스 서버에 패스워드를 설정하지 않을 경우엔 패스워드 설정대신 ALLOW_EMPTY_PASSWORD=yes 를 설정하면 된다.

 

위와 같이 도커 컴포즈 파일을 작성해주면, 마스터, 슬레이브, 센티널이 모두 설정한 네트워크(funfit) 내에서 동작한다. 

스프링과의 연동을 위한 설정 파일

그리고 스프링에 센티널을 통해 마스터 서버의 주소를 받아와서 연결해야 한다. 이에 대한 코드는 다음과 같다.

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.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

@Configuration
public class RedisConfig {

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {

        RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration()
                .master("mymaster")
                .sentinel("redis-sentinel-1", 26379) 
                .sentinel("redis-sentinel-2", 26379)
                .sentinel("redis-sentinel-3", 26379);
        sentinelConfiguration.setPassword("1234");

        LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(sentinelConfiguration);

        return connectionFactory;
    }
}

 

  • master(...): 센티널이 감시할 마스터의 마스터 이름을 적어주면 된다.
  • sentinel(...): 센티널의 호스트 이름과 포트 번호를 적어주면 된다. 참고로 스프링부트와 레디스는 모두 funfit이라는 같은 네트워크 내에서 구동되는 컨테이너이다. 따라서 스프링부트가 26780:26379인 레디스 센티널 서버에 접근할 때는 26380이 아닌 26379로 접근해야 한다.

테스트

빌드 후 docker compose up 명령어를 통해 실행시켰다.

6379, 6380 둘 다 실행 상태

그리고 마스터, 슬레이브, 센티널 서버의 redis cli에 접속해서 정보를 확인했다.

  • 6379: 자신이 마스터이며, 172.19.0.7:6379가 자신의 슬레이브이다. 
  • 6380: 자신이 슬레이브이며, redis-master:6379가 자신의 마스터이다.
  • 센티널: 마스터인 172.19.0.5:6379를 감시하고 있다.

6379 shutdown

  • 6380: 기존 슬레이브가 새로 마스터로 승격되었다. 그리고 자신의 슬레이브는 없다.
  • 센티널: 새로 승격된 마스터인 172.19.0.7:6379를 감시하고 있다.

6379 재실행

  • 6379: 슬레이브이며, 새로 승격된 마스터인 172.19.0.7:6379의 슬레이브다.
  • 6380: 여전히 마스터이며 자신의 슬레이브가 추가되었다.
  • 센티널: 여전히 마스터인172.19.0.7:6389를 감시한다.

 


Reference