Redis Sentinel을 이용한 고가용성 +EC2에 Docker-Compose를 이용한 실습

Redis Sentinel

Redis 공식문서에는 다음과 같이 소개되고 있다.

High availability with Redis Sentinel for non-clustered Redis

 

한글로 직역하자면 Redis Cluster를 사용하지 않을 때 Redis에 고가용성을 제공한다라는 뜻이다.

지난 포스팅때에는 Redis Replication(Redis 복제)에 대해 설명하였는데 거기에 HA의 개념을 덧붙였다고 생각하면 된다.

 

Sentinel 기능의 전체 목록

모니터링 마스터 및 Replication 인스턴스가 예상대로 작동하는지 지속적으로 확인
알림 모니터링되는 Redis 중 문제가 있음을 API를 통해 알릴 수 있다.
자동 장애 조치 예상대로 작동되지 않는 경우 Replication를 Master로 승격시켜 새 Master를 사용하도록 재구성
Config Provider 장애 조치가 발생하면 Sentinel 들은 새 Master 주소를 보고.

 

Redis Sentinel 분산 시스템

Redis Sentinel은 분산 시스템으로 아래의 장점이 존재한다.

  1. 여러 Sentinel이 주어진 마스터를 더 이상 사용할 수 없다는 것을 동의하고 실패 감지가 수행된다.
  2. 모든 Sentinel 프로세스가 동작되지 않는 경우에도 Sentinel이 작동하므로 장애에 대해 시스템이 견고해진다.

 

Redis Sentinel 실행

실행 파일을 사용하는 경우 redis-sentinel 명령줄을 사용하여 Sentinel을 실행할 수 있다.

redis-sentinel /{path}/{to}/sentinel.conf

 

redis-server 명령줄을 이용하여 Sentinel 모드에서 시작하는 실행 파일을 직접 사용 가능

reids-server /{path}/{to}/sentinel.conf --sentinel    # ditto

 

Redis 준비

  1. Sentinel 환경을 구축하기 위하여 최소 3개의 Sentinel 인스턴스가 필요함.
  2. 3개의 Sentinel 인스턴스는 독립적인 방식으로 실패하는 것으로 여겨지는 컴퓨터 또는 가상 머신에 배치되어야 한다. 이 포스팅에서는 docker 엔진 위에서 예제를 실행한다.

Redis Replication에서 구축했던 아키텍쳐이다.

이전 포스팅에도 얘기했듯이 Repilcation은 단순 복제 기능만 제공하고, failOver 기능은 제공하지 않기 때문에 이러한 기능은 Sentinel이 지원을 한다. 잊어버렸다면 아래 포스팅을 다시! 확인하자!

 

Sentinel 배포

Sentinel은 failOver를 수행하기 위해 항상 대다수와 대화해야하므로 아래 그림과 같이 두 개의 Sentinel만 사용하는 것은 하지 않는다.

잘못된 방법

이 설정에서 Master가 실행 중에 작동을 멈추면 Sentinel1도 작동을 멈춘다. 그래서 다른 상자 Sentinel2는 장애 조치를 승인할 수 없으므로 시스템을 사용할 수 없게된다고 합니다. 따라서 항상 세개의 서로 다른 공간에 적어도 세 개의 Sentinel을 배치하도록 해야한다.

3대의 Redis Sentinel의 구축

 

Sentinel, Docker, NAT 및 가능한 Solution

Docker는 포트 매핑이란 기술을 사용한다. Docker 컨테이너 내부에서 실행되는 프로그램은 프로그램이 사용한다고 생각하는 포트와 다른 노트로 노출될 수 있다. 이 특징은 동일한 서버에서 동시에 동일한 포트를 사용하여 여러 컨테이너를 실행하기 위해 유용하다.

 

예시

  • MySQL(3306) : -p 3333:3306
  • Redis(6379) : -p 9999:6379

 

 

Docker는 포트가 다시 매핑될 수 있는 NAT(Network Address Translation) 설정이 있으며 포트 뿐만 아니라 IP 주소도 있다.

포트 및 주소를 다시 매핑하는 순간 Sentinel은 다음 두 가지 문제가 발생한다.

  1. 각 Sentinel은 연결을 위해 수신 대기 중인 포트 및 IP 주소를 알리는 Hello 메시지를 기반으로 하기 때문에 자동 검색이 더 이상 작동하지 않는다.
  2. 복제본은 TCP 연결의 원격 피어를 확인하는 마스터에 의해 감지되는 반면 포트는 잘못되었을 수 있다.

 

 

Redis Sentinel 시작

  • Sentinel 인스턴스가 포트 5000,5001,5002에서 실행된다고 가정한다.
  • Redis Master와 Replication은 각각 6379, 6380에서 실행중이라고 가정한다.

 

세 개의 Senitnel 구성 파일

port [5000, 5001, 5002] # 각 Sentinel 포트
sentinel monitor mymaster 127.0.0.1 6379 2    # 마스터 세트를 mymaster로 지정
sentinel down-after-milliseconds mymaster 5000    # 5초안에 응답못하면 실패한 것으로 감지
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1    

 

센티넬에게 마스터 상태 묻기

redis-cli에서 Senitnel 명령어로 Redis Master 모니터링 하기

$ redis-cli -p 5000
127.0.0.1:5000> sentinel master mymaster
 1) "name"
 2) "mymaster"
 3) "ip"
 4) "127.0.0.1"
 5) "port"
 6) "6379"
 7) "runid"
 8) "953ae6a589449c13ddefaee3538d356d287f509b"
 9) "flags"
10) "master"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "735"
19) "last-ping-reply"
20) "735"
21) "down-after-milliseconds"
22) "5000"
23) "info-refresh"
24) "126"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "532439"
29) "config-epoch"
30) "1"
31) "num-slaves"
32) "1"
33) "num-other-sentinels"
34) "2"
35) "quorum"
36) "2"
37) "failover-timeout"
38) "60000"
39) "parallel-syncs"
40) "1"
  1. num-other-sentinels가 2이므로 Sentinel을 두 개 더 감지했음을 알 수 있다.
  2. flags 마스터가 다운된 경우
  3. num-slaves는 1로 설정되어있으므로 Sentinel도 마스터에 연결된 복제본이 있음을 감지합니다.

추가 명령어

SENTINEL replicas mymaster    # 마스터에 연결된 복제본에 대한 정보
SENTINEL sentinels mymaster   # 다른 Sentinel에 대한 정보

현재 마스터의 주소 얻기

SENTINEL get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6379"

 

 

Docker-compose로 Sentinel 환경 구축하기

 version: '3'

services:
    redis:
        image: 'bitnami/redis:latest'
        container_name: redis-master
        environment:
          - REDIS_REPLICATION_MODE=master
          - ALLOW_EMPTY_PASSWORD=yes
        networks:
          - test-network
        ports:
          - 6379:6379

    redis_slave-1:
        image: 'bitnami/redis:latest'
        container_name: redis-slaves-1
        environment:
          - REDIS_REPLICATION_MODE=slave
          - REDIS_MASTER_HOST=redis
          - ALLOW_EMPTY_PASSWORD=yes
        ports:
          - 6479:6379
        depends_on:
          - redis
        networks:
          - test-network

    redis_slave-2:
        image: 'bitnami/redis:latest'
        container_name: redis-slaves-2
        environment:
          - REDIS_REPLICATION_MODE=slave
          - REDIS_MASTER_HOST=redis
          - ALLOW_EMPTY_PASSWORD=yes
        ports:
          - 6579:6379
        depends_on:
          - redis
        networks:
          - test-network
		redis-sentinel-1:
        image: 'bitnami/redis-sentinel:latest'
        container_name: redis-sentinel-1
        environment:
            - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
            - REDIS_MASTER_HOST=redis
            - REDIS_MASTER_PORT_NUMBER=6379
            - REDIS_MASTER_SET=mymaster
            - REDIS_SENTINEL_QUORUM=2
        depends_on:
            - redis
            - redis_slave-1
            - redis_slave-2
        ports:
            - '26379:26379'
        networks:
            - test-network

    redis-sentinel-2:
        image: 'bitnami/redis-sentinel:latest'
        container_name: redis-sentinel-2
        environment:
            - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
            - REDIS_MASTER_HOST=redis
            - REDIS_MASTER_PORT_NUMBER=6379
            - REDIS_MASTER_SET=mymaster
            - REDIS_SENTINEL_QUORUM=2
        depends_on:
            - redis
            - redis_slave-1
            - redis_slave-2
        ports:
            - '26380:26379'
        networks:
            - test-network
		redis-sentinel-3:
        image: 'bitnami/redis-sentinel:latest'
        container_name: redis-sentinel-3
        environment:
            - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
            - REDIS_MASTER_HOST=redis
            - REDIS_MASTER_PORT_NUMBER=6379
            - REDIS_MASTER_SET=mymaster
            - REDIS_SENTINEL_QUORUM=2
        depends_on:
            - redis
            - redis_slave-1
            - redis_slave-2
        ports:
            - '26381:26379'
        networks:
            - test-network
networks:
    test-network:
        external: true

 

참고

https://redis.io/docs/management/sentinel/

 

High availability with Redis Sentinel

High availability for non-clustered Redis

redis.io

https://www.youtube.com/watch?v=92NizoBL4uA&t=25s 

'DevOps' 카테고리의 다른 글

Jenkins VS GitHub Actions과 그 특징  (0) 2023.08.16
Redis Replication 구축  (3) 2023.03.02
Docker를 이용한 Nginx 설치 및 config 수정  (0) 2023.02.03