ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Redis 고가용성으로 사용하기 with Sentinel
    💻 프로그래밍/DB 2022. 1. 2. 10:43

    엑스맨 센티넬!! 이 아니라 레디스 센티넬

    안녕하세요! 운동하는 개발자 Jay 입니다. 오늘의 주제는 Redis를 고가용성으로 사용하는 방법에 대해 이야기해보려고 합니다. 고가용성이란 말 그대로 "가용성이 높다"라는 의미로 절대 고장 나지 않음을 의미한다고 위키백과가 그러네요 ㅋㅋㅋ

     

    지옥...을 경험...

    보통 Redis는 1개를 사용하지 않고 Master <-> Slave 관계로 Replication 하여 사용합니다. 아시다시피 1대의 Redis만 사용하고 있다면 장애상황에서 엄청난 헬(Hell)을 경험할 수 있습니다.

     

    Replication 하여 사용하는 일반적인 Redis 구성

    위 이미지 처럼 replicaiton 되어있는 상황에서, Master Redis가 장애가 나면 slave로 client는 연결되고 write는 불가, read만 가능한 상황이 됩니다. 이런상황에서 write가 안되기 때문에 redis write 하는 로직이 있으면 사이드 이팩트(Side Effect)가 생길 수 있습니다.

     

    그렇기 떄문에 Master를 다시 살리거나 Slave였던 Redis를 Master로 승격시켜야 합니다.

     

    Redis 장애상황 예시

    근데 이런 장애상황에서 이 모든 것을 개발자가 수동으로 해야 하고, 인지하기까지 오래 걸린다면 장애는 더욱 길어질 것입니다. 게다가 장애라는 게 언제 생길지도 모르는 거고 이 모든것을 사람이 손으로 해야 한다?... 네 이건 좀 아니죠.

     

    서버신에게 기도하는 서버개발자들

    물론 Redis 장애가 잦은 상황은 아닐 것입니다. 그래도 서버, 인프라는 365일 정상적으로 운영해야 하기 때문에 이런 장애를 미리 대응할 수 있는 시스템을 갖춘다면 좋을 거예요!

     

    바로! 그래서 Redis에서는 Sentinel이라는 기능을 제공합니다. 간단히 말씀드리자면 위에 예시였던 장애 상황에 개발자가 모니터링하고 수동으로 처리하는 것을 Sentinel이라는 것이 대신 모니터링하고 자동으로 failover 해줍니다.

     

    역시 자동화가 짱이야~

    자동! 이 얼마나 아름다운 단어입니까 ㅋㅋㅋ (역시 모든 건 자동화해야 해... 칼퇴를 합시다 여러분 ㅋㅋㅋ) 그래서 오늘은 Docker로 Redis Sentinel 환경을 구성하여, Auto Failover와 redis들이 어떻게 master를 재선출하고 동작하는지를 실습해보려고 합니다.

     

    🛠 sentinel 환경 구성하기 (docker compose)


    아래와 같이 도커 컴포즈(Docker-compose) 파일을 구성해 줍니다. Master 1대, Slave2대와 Sentinel 설정이 있습니다. Sentinel은 도커 컴포즈 실행시킬 때 3개로 구성하도록 옵션을 추가할 예정입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    version: '3.1'
     
    networks:
      app-tier:
        driver: bridge
     
    services:
     
      redis:
        image: 'bitnami/redis:latest'
        container_name: redis
        # restart: always
        environment:  
          - REDIS_REPLICATION_MODE=master
          - ALLOW_EMPTY_PASSWORD=yes
        ports:
          - "6379:6379"
        networks:
          - app-tier
        
      redis-slave-1:
        image: 'bitnami/redis:latest'
        container_name: redis-slave-1
        # restart: always
        environment:
          - REDIS_REPLICATION_MODE=slave
          - REDIS_MASTER_HOST=redis
          - ALLOW_EMPTY_PASSWORD=yes
        ports:
          - "6380:6379"
        
        depends_on:
          - redis   
        networks:
          - app-tier
            
      redis-slave-2:
        image: 'bitnami/redis:latest'
        container_name: redis-slave-2
        # restart: always
        environment:
          - REDIS_REPLICATION_MODE=slave
          - REDIS_MASTER_HOST=redis
          - ALLOW_EMPTY_PASSWORD=yes
        ports:
          - "6381:6379"
        
        depends_on:
          - redis   
        networks:
          - app-tier
     
      redis-sentinel:
        image: 'bitnami/redis-sentinel:latest'
        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-26381:26379'
        networks:
          - app-tier
     
    cs

    Redis와 Sentinel을 3대로 구성하는 이유는 Redis가 Master를 선출하는 과정에서 투표(vote)를 하게 됩니다.  다수결로 Master 선출 여부를 결정할 수 있기 때문에 홀수로 구성하게 됩니다. 그렇지 않으면 정상적으로 auto failover를 하지 못할 수 있습니다.

    -  Redis/Sentinel 실행

    docker-compose up --scale redis-sentinel=3 -d

    docker compose 명령어를 실행하면 아래처럼 redis, sentinel 구성이 만들어진 걸 확인할 수 있습니다.

    Master Redis 에서 role 명령어 실행시

    마스터 Redis에 접속해서 redis-cli를 통해 role을 확인하면 현재 접속한 Redis의 Role과 Slave 정보들도 함께 확인이 가능합니다. Slave의 IP, Port, replication offset 등의 정보등을 확인할 수 있습니다.

     

    Slave Redis에서 role 명령어 실행시

    마찬가지로 슬레이브에서도 동일한 명령어로 부가 정보를 확인할 수 있습니다.

     

    Sentinel info 확인

    Sentinel에 접속하여 info sentinel 명령어를 사용하면 현재 구성된 sentinel의 정보들을 확인할 수 있습니다.

     

    -  Redis Pub/Sub

    Redis는 publish/subscribe 개념으로 channel(채널)을 통해 메시지를 주고 받습니다. 모든 메세지를 받는게 아니라 subscribe(구독)을 한 채널에서만 메세지를 받는 방식입니다. publish는 말그대로 메세지를 발행하는 역할을 합니다.

     

    Sentinel은 Redis의 Pud/Sub 기능을 이용해 다른 Sentinel과 메시지를 주고받으면서 상태를 체크합니다. 

    __sentinel__:hello  이라는 채널로 모든 Sentinel은 메시지를 주고받습니다.

    ip:port:runid 를 나타내며, 마지막 값은 failover 할지 말지를 설정하는 값입니다.

     

    psubscribe 명령어로 모든 패턴(*)의 채널 메세지를 출력

    psubscribe 명령어를 사용하면 특정 패턴의 채널을 구독하여 주고받는 메시지들을 확인할 수 있습니다. 

    pusub 명령어 중 numsub을 사용하면 특정 채널의 구독 중인 클라이언트 개수를 보여줍니다. 현재 3개의 sentinel이 구독 중이기 때문에 3이라는 숫자가 출력되는 것을 확인할 수 있습니다.

    특정 채널을 구독후 메세지를 받는지 확인

    위처럼 특정 채널을 구독 중일 때 메시지를 발행하게 되면 위 이미지처럼 출력되는 것을 확인할 수 있습니다.

     

    💡 FailOver 실습


    현재 실행 중인 Master Reids를 down 시켜서 새로운 Master의 선출이 되는 과정을 확인해보겠습니다.

    아래는 결론적으로 새로운 Master가 선출되는 Before/After입니다.

    새로운 마스터가 산출된 정보

    위 이미지의 정보를 보시게 되면 처음에 slave 2개로 정보가 있었는데, After에 salve가 1개로 변경된 것을 확인할 수 있습니다. Master 주소도 바뀐 것을 확인할 수 있습니다.

    이 과정을 log로 확인하게 되면 아래와 같습니다.

     

    1. sdown(subjectively down)

    sdown(주관적 다운) 이라고 해서 서버가 다운되었는지를 판단한다. sdown이라고 하는 이유는 실제로 내 판단은 이러한데 다른 sentinel의 판단은 모르기 때문에 주관적이라고 한다. 다운된 서버가 Master일 경우에는 다른 Sentinel들에게 실제로 Master가 다운되었는지 질의를 합니다.

     

    sdown 로그

    2. odown(objectively down)

    질의가 왔을 때 자신이 바라보는 Master가 다운되었는지 응답합니다. 자신을 포함해서 마스터가 다운되었다고 응답한 센티널 수가 Quorum(쿼럼) 이상이면 센티널은 해당 마스터가 실제로 다운되었다고 판정합니다. 이것을 객관적 다운(odown)이라고 합니다. 172.28.0.2 (Master) 서버가 다운되었다고 판단하고 있습니다.

     

    3. new-epoch, try-failover, vote-for-leader

    odown 인 경우 Sentinel은 장애조치를 하게 됩니다. vote-for-leader는 말 그대로 master를 선출하는 투표입니다. 다른 sentinel은 처음 응답으로 온 master산출 redis에 대해 투표를 진행합니다. 

     

    4. slaveof-noone

    선정된 Slave를 새로운 Master로 승격시킨다는 log입니다. 아래 이미지에서는 172.28.0.3을 Master로 승격시키고 있습니다.

    5. switch-master

    장애조치 완료입니다. 말 그대로 Master가 변경(switch), 승격되었다는 로그입니다.

    로그를 보시면 172.28.0.2에서 172.28.0.3으로 Master가 변경(승격)되었음을 볼 수 있습니다.

     

    쿠버네티스 Redis Senitnel에서는 기존 Master가 죽고 새로 뜨는 경우에 Sentinel에 slave로 자동으로 붙는 기능들을 지원합니다. (이 부분은 저도 자세히는 모르나 회사에서 사용 중인 Sentinel은 자동으로 되네요)

     

    우리가 직접 다운된 Redis를 살려서 Slave로 Sentinel과 붙이기 위해서는 별도의 스크립트로 실행되도록 작업해야 합니다. 오늘 실습에서는 실제로 Redis Sentinel이 어떻게 구성되어있고, 장애조치(Failover)가 일어나는 과정과 일부 명령어만 확인해봤습니다.

     

    👋 마치며


    이번 포스팅에서 Reis, Sentinel의 모든 걸 알아본 건 아니지만, Sentinel을 사용함으로써 Redis를 고가용성으로 사용하고, Sentinel Failover 과정이 대략적으로 이렇다 등을 알 수 있었던 것 같습니다.

     

    개인적으로 애플리케이션을 주로 개발하는 백엔드 개발자지만 인프라에 관한 기술적인 지식들도 매우 깊으면 좋겠지만, 얕고 넓게라도 알고 있어야 한다고 생각합니다. 그리고 회사에서 주로 사용하는 기술은 좀 더 깊게 보면 되고요! (인프라 알못의 말... ㅋㅋㅋ)

     

    그럼 오늘도 즐거운 하루 되시고 서버 장애가 없는 하루가 되길바라며~

     

    참고 사이트

    센티널 리더 선출 과정과 장애 조치 과정

    Redis의 특징과 Sentinel 구성에 대해서

    [Redis] master-slave(replication) 구축하기

    https://garimoo.github.io/database/2019/09/06/redis_ha.html

    댓글

운동하는 개발자 JAY-JI