[프로젝트] Redis Master & Slave + Sentinel || 설정관련

박상준·2024년 3월 19일
1

REDIS

목록 보기
2/20

  • 여기서 슬레이브 하나만 빠지면 위와 같은 구조이다.
version: '3.8'

networks:
  app-tier:
    driver: bridge

services:
  redis-master:
    image: "bitnami/redis:7.2.4"
    hostname: redis-master
    container_name: eighteen-be-redis-master
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
      - REDIS_REPLICATION_MODE=master
    ports:
      - "6379:6379"
    networks:
      - app-tier

  redis-slave-1:
    image: "bitnami/redis:7.2.4"
    hostname: redis-slave-1
    container_name: eighteen-be-redis-slave-1
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
      - REDIS_MASTER_HOST=redis-master
      - REDIS_REPLICATION_MODE=slave
    ports:
      - "6479:6379"
    depends_on:
      - redis-master
    networks:
      - app-tier

  redis-slave-2:
    image: "bitnami/redis:7.2.4"
    hostname: redis-slave-2
    container_name: eighteen-be-redis-slave-2
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
      - REDIS_MASTER_HOST=redis-master
      - REDIS_REPLICATION_MODE=slave
    ports:
      - "6579:6379"
    depends_on:
      - redis-master
      - redis-slave-1
    networks:
      - app-tier

  redis-sentinel-1:
    image: 'bitnami/redis-sentinel:7.2.4'
    hostname: redis-sentinel-1
    container_name: eighteen-be-redis-sentinel-1
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2
    ports:
      - '26379:26379'
    networks:
      - app-tier

  redis-sentinel-2:
    image: 'bitnami/redis-sentinel:7.2.4'
    hostname: redis-sentinel-2
    container_name: eighteen-be-redis-sentinel-2
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2
    ports:
      - '26380:26379'
    networks:
      - app-tier

  redis-sentinel-3:
    image: 'bitnami/redis-sentinel:7.2.4'
    hostname: redis-sentinel-3
    container_name: eighteen-be-redis-sentinel-3
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2
    ports:
      - '26381:26379'
    networks:
      - app-tier

volumes:
  mysql-data:
  • Docker Compose 를 사용해 Redis 마스터- 슬레이브 복제 구성을 설정하는 예시 설정 (위)

  • 왜 프로젝트에서 Master & Slave 구조를 채택했는가?

    [NHN FORWARD 2021] Redis 야무지게 사용하기 (youtube.com)

    • NHN Forward 발표 자료에서 아키텍처 선택 기준을 참고하였다.

      일단 다이어그램에서 HA 기능이 보인다.

      HA 기능?

      • High Availability ⇒ 고 가용성
      • 시스템이나 서비스에 장애가 발생하더라도 지속적으로 운영될 수 있도록 설계된 기능이다.
      • 시스템의 신뢰성을 높일 수 있다.
    • HA 기능의 경우
      1. 단일 레디스로 구성할 것인가
      2. 다중 레디스로 구성할 것인가

      2가지 분기로 나눠서 생각해야한다.
      
      - 단일 레디스 == 오직 하나의 Master 레디스만 존재
          - 만약 오류가 발생하여 Master 레디스(인스턴스)가 종료되는 경우, 수동으로 Master 재시작을 해줘야한다.
      - 다중 레디스
          - Master 에 장애가 발생하는 경우 Slave 레디스를 생성해놓고 대안으로 사용하는 구조가 가능함.
          - 해당 과정에서 Replication 이라는 DB 복제가 필연적임

      가용성을 높이기 위해 오버 엔지니어링이 될 수 있더라도, 다중 레디스를 구성하기로 했다.

    • 또한 다중 레디스를 구성하는 경우

      • 복제 를 슬레이브에 해줘야한다.

      • 소스상에선

          redis-slave-1:
            image: "bitnami/redis:7.2.4"
            hostname: redis-slave-1
            container_name: eighteen-be-redis-slave-1
            environment:
              - ALLOW_EMPTY_PASSWORD=yes
              - REDIS_MASTER_HOST=redis-master
              - REDIS_REPLICATION_MODE=slave
            ports:
              - "6479:6379"
            depends_on:
              - redis-master
            networks:
              - app-tier
        
          redis-slave-2:
            image: "bitnami/redis:7.2.4"
            hostname: redis-slave-2
            container_name: eighteen-be-redis-slave-2
            environment:
              - ALLOW_EMPTY_PASSWORD=yes
              - REDIS_MASTER_HOST=redis-master
              - REDIS_REPLICATION_MODE=slave
            ports:
              - "6579:6379"
            depends_on:
              - redis-master
              - redis-slave-1
            networks:
              - app-tier
    • 요 부분이 되는데

    • 하나의 마스터 Redis 인스턴스와 두 개의 슬레이브 Redis 인스턴스 ( redis-slave-1 , redis-slave-2 ) 가 포함되어 있다.

      공통 속성

      • 이미지

        • 모든 인스턴스를 최신 버전인 bitnami/redis:7.2.4 버전을 채택하였다.

        • hostname , container_name

          • 컨테이너 내부에서 사용할 호스트 이름과 컨테이너 이름이다
          • hostname 의 경우 네트워크 내에서 컨테이너를 식별할 수 있는 고유한 이름이 되기에 중요하다.
        • ports

          • “외부:내부” 구조로 구성되어 있다.

          • 외부 요청을 컨테이너의 6379 로 전달한다

            마스터 - 슬레이브 간의 예시

            • redis-master 인스턴스는
              • “6379:6379”
                • 6379 포트로 들어와서 6379포트로 전달
            • redis-slave-1 인스턴스는
              • “6380:6379”
                • 6380 포트로 들어와서 6379포트로 전달
            • 결국 6379 포트인 master 에서 작업을 수행함을 알 수 있음.
        • network

          • 컨테이너가 연결될 네트워크를 지정한다.

          • 초기에 docker-compose 에서 설정해놓았던

            networks:
              app-tier:
                driver: bridge
            • 와 관계있다.

            • 이게 무엇이냐..

              • 일단 DOCKER 가 등장한 이유중에 하나가 될 수 있다.

                격리 및 통신 이 그 원인이다.

                • 격리

                  • Docker 네트워크는 컨테이너 간의 격리를 제공한다.
                • 통신

                  • app-tier ( 그냥 내가 정한 네트워크 이름 ) 네트워크를 사용함으로서

                  • 마스터와 슬레이브 간의 통신 경로를 지정한다.

                  • 컨테이너 간의 통신을 위하여 bridge 모드로 네트워크를 설정한 것이다.

                  • 레디스 친구들은 레디스 끼리 통신하고 연관되어 있어야하니 너네 끼리는 서로에 대해 인지하렴~ 인 것이다.

                    또한 bridge 모드는

                    • 통신의 유연성을 제공한다고 한다.
                    • SOLID 원칙중에 개방 폐쇄 원칙이 존재한다.
                      • 개방 폐쇄 원칙은 새로운 서비스를 추가하거나 변경하는 경우 기존 네트워크 구성을 수정하지 않고 확장하는 것을 말하는데
                      • bridge 모드는 마스터 슬레이브외에 센티넬.. 등의 다른 추가적인 서비스를 동일한 네트워크에 묶을 수 있다.

      마스터 속성

    • REDIS_REPLICATION_MODE = master
      - 레디스 서버의 복제 모드를 마스터로 설정하는 것이다.
      - 마스터는 데이터의 원본을 가지며, 슬레이브에 데이터를 복제한다.

      슬레이브 속성

    • REDIS_MASTER_HOST= redis-master

      • 슬레이브가 데이터를 복제할 마스터 서버의 호스트 이름을 지정한다.
      • 여기서는 redis-master 호스트(마스터 서버)에서 데이터를 복제합니다.
    • REDIS_REPLICATION_MODE = slave
      - 레디스 서버의 복제 모드는 슬레이브로 설정한다.
      - 마스터로부터 데이터를 복제하여 , 읽기 요청을 처리하거나, 마스터에 장애가 발생한 경우 대체 역할을 수행

      공통 환경 변수

    • ALLOW_EMPTY_PASSWORD = yes
      - 비밀번호없이 레디스 서버에 접근함

      ### 해당 설정은 운영될 환경에서는 절대로 설정하면 안된다.

      의존성 관련

    • depends_on

      • 특정 서비스에 시작되기전에 ~~ 한 서비스가 먼저 시작되어야 한다고 알려주는 것이다.
      • redis-slave-1 혹은 redis-slave-2 의 경우
        • redis-master 가 먼저 시작해야 작동해야함

도커 Intellij 에서 쉽게 구동하는 방법

  1. docker-compose 파일 services 실행

    • 혹은 docker compose up -d를 수행하면된다.

  2. 서비스에서 이미지들을 pulling 하는 모습

  3. 정상적으로 수행됨을 알 수 있다.

배포되었던 docker 내용을 전부 지우고 싶은 경우

  1. docker-compose down

    • 네트워크와 컨테이너를 모두 삭제
      • 볼륨은 삭제되지 않는다.

Replication 확인 방법

  1. docker-desktop 에서 redis-master 인스턴스의 로그만 체크해봐도 replication 이 수행됨을 알 수 있다.

    • 172.21.0.3 혹은 172.21.0.4 는 각각 slave-1 과 slave-2 에 해당 된다.

Sentinel FailOver 대비 Master & Slave Replacement 설정

  redis-sentinel-1:
    image: 'bitnami/redis-sentinel:7.2.4'
    hostname: redis-sentinel-1
    container_name: eighteen-be-redis-sentinel-1
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2
    ports:
      - '26379:26379'
    networks:
      - app-tier

  redis-sentinel-2:
    image: 'bitnami/redis-sentinel:7.2.4'
    hostname: redis-sentinel-2
    container_name: eighteen-be-redis-sentinel-2
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2
    ports:
      - '26380:26379'
    networks:
      - app-tier

  redis-sentinel-3:
    image: 'bitnami/redis-sentinel:7.2.4'
    hostname: redis-sentinel-3
    container_name: eighteen-be-redis-sentinel-3
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2
    ports:
      - '26381:26379'
    networks:
      - app-tier
  • 환경 설정부분만 보면 될 듯하다.

    • REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS

      • 레디스 센티넬이 구독한 서버가 3000 밀리세컨드 만큼 가동되지 않는 경우, failover(장애 조치) 를 시도한다.

        장애 조치

        • 밑의 그림같은 과정을 말함.
    • REDIS_SENTINEL_QUORUM

      • Sentinel 시스템이 마스터 서버에 장애가 발생했다고 판단하고 장애 조치를 시작하기 위해 필요한 최소한의 Sentinel 인스턴스의 수를 정의

      • 2 로 설정된 경우
        - 3개의 센티넬의 경우 2개 이상의 투표를 받은 slave 가 master 노드가 된다.

        센티넬은 무조건 3개 이상의 홀수로 설정해야한다

        • 투표가 동률이 되는 경우 선택이 불가능
        • failover 가 동작하지 않게 된다.

Sentinel 정상 동작 테스트

  • master instance 를 약 500 초 동안 재운다.

  • master 인스턴스가 3초 이상 동작하지 않음을 파악한 경우
    • 새로운 마스터를 선출하는 과정을 거친다.

    • 1:X 19 Mar 2024 17:01:18.523 # +monitor master mymaster 192.168.32.2 6379 quorum 2
      - mymaster 라는 이름의 마스터를 192.168.32.2 주소와 6379 포트에서 모니터링하기 시작한다.
      - 쿼럼은 2로 설정

      1:X 19 Mar 2024 17:01:18.524 * +slave slave 192.168.32.4:6379 192.168.32.4 6379 @ mymaster 192.168.32.2 6379
      1:X 19 Mar 2024 17:01:18.527 * +slave slave 192.168.32.3:6379 192.168.32.3 6379 @ mymaster 192.168.32.2 6379
    • slave 2개를 감지합니다
      - 2개의 슬레이브를 감지하고, mymaster 에 연결되어 있음을 확인한다.

      1:X 19 Mar 2024 17:01:20.182 * +sentinel sentinel 403c57ff71396630f2f894b49ba3662ddb151a48 192.168.32.5 26379 @ mymaster 192.168.32.2 6379
      1:X 19 Mar 2024 17:01:20.423 * +sentinel sentinel 85fb9fd730d7fc5995bd4cd04f4af770dc7b2d3e 192.168.32.6 26379 @ mymaster 192.168.32.2 6379
    • 센티넬 2개를 감지
      - 2개의 센티넬을 감지하고, 이들도 mymaster를 모니터링한다.

      1:X 19 Mar 2024 17:01:59.913 # +sdown master mymaster 192.168.32.2 6379
      1:X 19 Mar 2024 17:01:59.976 # +odown master mymaster 192.168.32.2 6379 #quorum 3/2
    • 주관적 (sdown) 및 객관적 다운 (odown) 상태 감지

      > 주관적 다운
      > 
      > - 특정 Sentinel 인스턴스가 마스터 - 슬레이브 와의 연결이 끊어졌다고 `개인적으로` 판단하는 상태
      > - 지금 판단하는 센티넬의 `개인적` 생각
      
      > 객관적 다운
      > 
      > - 여러 Sentinel 인스턴스들이 공통적으로 노드 ( 주로 마스터임 ) 가 다운되었다고 판단하는 상태를 말한다.
      > - Quorom (쿼럼) 이라는 다수결 원칙에 의해 결정된다.
      >     
      >     ### 실질적으로 시스템전체에서 해당 마스터 인스턴스가 실패했음을 인정한 상태 ⇒ 마스터가 죽었다!
      >     
      1:X 19 Mar 2024 17:02:00.955 # +switch-master mymaster 192.168.32.2 6379 192.168.32.4 6379
    • 마스터와 slave 를 교체한다.

      • 192.168.32.4 6379 는 이전에는 slave 였지만, 새 마스터로 선출하고,
      • 이전 마스터는 새 마스터의 슬레이브로 재구성된다.

  • sentinel에서
    • redis-cli -p <sentinel 의 내부포트>
    • 입력후
    • info sentinel 명령어를 수행하면
      • 마스터노드가 192.168.32.4:6379 로 변경되었음을 알 수 있다.

docker compose 관련 수정사항 ( 2024 - 03 -21 )

```
  redis-master:
image: "bitnami/redis:7.2.4"
hostname: redis-master
container_name: eighteen-be-redis-master
environment:
  - ALLOW_EMPTY_PASSWORD=yes
  - REDIS_REPLICATION_MODE=master
volumes:
  - redis-master-data:/bitnami/redis/data:rw
command: redis-server --enable-debug-command yes --protected-mode no
ports:
  - "6379:6379"
networks:
  - app-tier

redis-slave-1:
  image: "bitnami/redis:7.2.4"
  hostname: redis-slave-1
  container_name: eighteen-be-redis-slave-1
  environment:
    - ALLOW_EMPTY_PASSWORD=yes
    - REDIS_MASTER_HOST=redis-master
    - REDIS_REPLICATION_MODE=slave
  ports:
    - "6479:6379"
  volumes:
    - redis-slave-1-data:/bitnami/redis/data:rw
  depends_on:
    - redis-master
  networks:
    - app-tier

redis-slave-2:
  image: "bitnami/redis:7.2.4"
  hostname: redis-slave-2
  container_name: eighteen-be-redis-slave-2
  environment:
    - ALLOW_EMPTY_PASSWORD=yes
    - REDIS_MASTER_HOST=redis-master
    - REDIS_REPLICATION_MODE=slave
  ports:
    - "6579:6379"
  volumes:
    - redis-slave-2-data:/bitnami/redis/data:rw
  depends_on:
    - redis-master
    - redis-slave-1
  networks:
    - app-tier

redis-sentinel-1:
  image: 'bitnami/redis-sentinel:7.2.4'
  hostname: redis-sentinel-1
  container_name: eighteen-be-redis-sentinel-1
  environment:
    - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
    - REDIS_MASTER_HOST=redis-master
    - REDIS_MASTER_PORT_NUMBER=6379
    - REDIS_MASTER_SET=mymaster
    - REDIS_SENTINEL_QUORUM=2
  depends_on:
    - redis-master
    - redis-slave-1
    - redis-slave-2
  ports:
    - '26379:26379'
  networks:
    - app-tier

redis-sentinel-2:
  image: 'bitnami/redis-sentinel:7.2.4'
  hostname: redis-sentinel-2
  container_name: eighteen-be-redis-sentinel-2
  environment:
    - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
    - REDIS_MASTER_HOST=redis-master
    - REDIS_MASTER_PORT_NUMBER=6379
    - REDIS_MASTER_SET=mymaster
    - REDIS_SENTINEL_QUORUM=2
  depends_on:
    - redis-master
    - redis-slave-1
    - redis-slave-2
  ports:
    - '26380:26379'
  networks:
    - app-tier

redis-sentinel-3:
  image: 'bitnami/redis-sentinel:7.2.4'
  hostname: redis-sentinel-3
  container_name: eighteen-be-redis-sentinel-3
  environment:
    - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
    - REDIS_MASTER_HOST=redis-master
    - REDIS_MASTER_PORT_NUMBER=6379
    - REDIS_MASTER_SET=mymaster
    - REDIS_SENTINEL_QUORUM=2
  depends_on:
    - redis-master
    - redis-slave-1
    - redis-slave-2
  ports:
    - '26381:26379'
  networks:
    - app-tier

volumes:
  mysql-data:
  redis-master-data:
  redis-slave-1-data:
  redis-slave-2-data:
- 볼륨 관련해서 문제가 있어서 이런식으로 수정 각각의 노드들이 독립적인 볼륨을 가지도록 설정
- 또한 permission 에러가 발생해서.. 수정했다 이유를 도저히 모르겠다.
profile
이전 블로그 : https://oth3410.tistory.com/

0개의 댓글