DB

[Redis] Redis-Sentinel 구축해보기

수수한개발자 2024. 2. 18.
728x90

 

 

 

 

센티널이란?

레디스의 자체 고가용성 기능이다.

센티널은 데이터를 저장하는 기존 레디스 인스턴스와는 다른 역할을 하는 별도의 프로그램이며,

페일오버 기능을 사용하면 마스터 인스턴스에 장애가 발생하더라도 레디스를 계속 사용할 수 있도록 동작해 레디스의 다운 타임을 최소화할 수 있다.

 

센티널의 기능

1. 모니터링

마스터, 복제본 인스턴스의 상태를 실시간으로 확인한다.

 

2. 자동 페일오버

마스터의 비정상 상태를 감지해 정상 상태의 복제본 중 하나를 마스터로 승격시킨다.

 

3. 인스턴스 구성정보 안내

센티널은 클라이언트에게 현재 구성에서의 마스터 정보를 알려준다.

페일오버가 발생하면 변경된 마스터 정볼르 재전달하기 때문에 페일오버가 발생하더라도 레디스의 엔드포인트 정보를 변경할 필요가 없다.

 

 

센티널 인스턴스 배치 방법

 

기본적으로 센티널은 물리적으로 서로 영향받지 않는 서버에서 실행되는 것이 좋다.
마스터의 장애를 감지할 수 있어야 하기 때문에 서로 다른 가용 영역에 배치하는 것이 일반적이다.

센티널은 최대 3대 이상 사용해야 하며 각각은 다른 물리 서버에 배치하는 것이 좋기 때문에 보통 하나의 서버에 레디스 프로세스와 센티널 프로세스를 동시에 실행 시킨다.

서버 A - 레디스 마스터, 센티널 1
서버 B - 레디스 복제본, 센티널 2
서버 C - 레디스 복제본, 센티널 3
서버 A 가 죽으면 서버 B와 C의 센티널 인스턴스는 새롭게 마스터가 될 복제본을 선출 한 두, 해당 복제본 인스턴스를 마스터로 승격시킨다. 기존 마스터를 보고 있던 클라이언트는 모두 서버 B에서 새롭게 선출된 마스터로 연결되며 레디스로 새롭게 들어오는 커넥션은 모두 마스터 IP 정보로 서버 B의 레디스 주소를 전달받는다.

서버 A가 복구 되면 센티널 인스턴스는 기존 마스터였던 서버 A의 레디스 인스턴스를 새롭게 마스터가 된 서버 B의 복제본이 되도록 연결 시킨다.
이러한 과정이 자동으로 구성되며 운영자의 개입이 필요하지 않다.

만약 서버의 리소스의 여유가 있다면 위와 같이 구성하면 좋지만 복제본이 2개까지 필요하지 않을 수도 있다.
그럴 경우 A, B 서버에는 동일하고 서버 C에는 센티널만 실행시키도록 배치할 수 있다.
센티널만 실행될 서버에는 데이터 저장 및 클라이언트 요청도 받지 않기 때문에 최저 사양의 스펙으로 구성해도 괜찮다.

 

 

센티널 동작 흐름

센티널의 동작 흐름을 알아보자

 

 

 

처음에는 한대의 master를 두고 2대의 복제본 노드를 갖는다. 

 

 

 

만약 Master 노드에 장애가 발생한다면 Sentinel은 투표를 통해 과반수를 얻으면 새로운 마스터를 선출하고 자동으로 페일 오버를 한다.

 

 

 

기존의 Master 노드가 복구 된다면 Slave 노드가 되어 새로운 Master 의 데이터를 복제한다.

센티널은 위와 같은 흐름으로 동작한다.

 

 

센티널 인스턴스 실행하기

위의 설명이 베스트지만 나는 로컬 환경에서 진행하였다.

Mac이므로 brew를 통해 레디스를 설치하였다.

 

 

  1. 로컬 환경에서 3개의 레디스와 3개의 센티널을 다른 포트로 실행시킨다.
  2. 위의 환경을 맞춰주기 위하여 레디스 설정파일과 센티널 설정파일을 3개씩 만들어준다.

 

redis.conf 파일의 경로는 다음과 같다.

/opt/homebrew/etc

 

 

redis 설정 파일 복사

cp redis.conf redis_6380.conf
cp redis.conf redis_6381.conf
cp redis.conf redis_6382.conf

 

 

 

현재 파일 목록들이다.

 

레디스 서버를 실행할 때 위의 파일들을 읽어 실행하기 때문에 설정을 변경해줘야한다.

 

vi redis_6380.conf
port 6380

vi redis_6381.conf
# 마스터의 IP와 포트를 작성해준다.
replicaof 127.0.0.1 6380
repl-timeout 60
port 6381


vi redis_6382.conf
# 마스터의 IP와 포트를 작성해준다.
replicaof 127.0.0.1 6380
port 6382

 

 

레디스 실행

redis-server redis_6380.conf
redis-server redis_6381.conf
redis-server redis_6382.conf

 

레디스 접속

redis-cli -p 6380
redis-cli -p 6381
redis-cli -p 6382

 

 

6380 포트 마스터에서 데이터를 삽입하면 정상적으로 들어가는것을 확인할 수 있다.

 

 

6381 복제본 노드에서도 데이터를 확인할 수 있으므로 복제가 잘 된것을 확인할 수 있다.

 

슬레이브 노드는 읽기만 가능하기 때문에 여기서 마스터 노드가 종료 된다면 평생 데이터를 쓸수 없는 상황이 된다.

 

# 6381 port redis
replica no one
config rewrite

#6382 port redis
replicaof 127.0.0.1 6381
config rewrite

 

여기서 슬레이브노드로 접속해 위의 명령어를 통해 다시 마스터를 선출할 수 있지만 운영환경에서 매번 이렇게한다면 유지보수 할 수 없을 것이다.

 

 

이제 센티널을 이용해 자동 페일오버를 사용해보자.

센티널은 운영자의 개입없이 자동으로 투표를 통해 마스터로 승격을 해준다.

 

 

 

 

 

 

 

vi redis-sentinel_26380.conf

port 26380
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6380 2

# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 10000

 

down-after-milliseconds : 이 시간동안 응답이 없으면 장애로 판단하고 페일오버를 한다.

센티널은 마스터와 복제보을 포함한 모든 레디스 프로세스를 모니터링하지만 구성 파일에는 복제본 정보를 직접 인력하지 않아도 된다.  
센티널 프로세스가 시작하면 마스터에 연결된 복제본을 자동으로 찾아내는 과정을 거친다.

 

센티널 실행

redis-sentinel redis-sentinel_26380.conf
redis-sentinel redis-sentinel_26381.conf
redis-sentinel redis-sentinel_26382.conf

 

 

정상적으로 센티널이 실행된 모습이다.

 

이제 마스터노드인 6380이 다운되었을때 자동으로 Slave를 새로운 마스터로 승격시키는지 확인해보자.

 

서버를 그냥 끄는 방법도 있고 아래와 같은 명령어를 통해 서버를 종료시킬 수 도 있다.

redis-cli -h <master-host> -p <master-port> shutdown
redis-cli -h 127.0.0.1 -p 6380 shutdown

 

위에서 down-after-milliseconds 설정한 시간 만큼 대기를 해야한다.

 

 

6381 포트의 레디스를 보며 MASTER MODE enabled 로그가 보이며 6382 포트의 레디스를 복제본으로 받는것을 확인할 수 있다.

 

또한 info replication 명령어로 확인하면 master로 변경된것을 확인할 수 있다.

 

 

6382 포트의 레디스를 보면 replicaof 127.0.0.1 6381 커맨드를 통해 6381 포트의 레디스 인스턴스가 자기의 마스터라는 것을 자동으로 실행한다.

 

이제 센티널의 로그를 확인해보자

 

마스터의 장애 상황 감지
센티널은 down-after-milliseconds 파라미터에 지정된 값 이상 동안 마스터에 보낸 PING에 대해 유효한 응답을 받지 못하면 마스터가 다운됐다고 판단한다.  

sdown, odwon 실패 상태로 전환
하나의 센티널 노드에서 레디스 마스터 인스턴스에 대해 응답을 늦게 받으면 그 센티널은 마스터의 상태를 sdown으로 플래깅한다.  
sdown은 subjectly down 즉 주관적인 다운 상태를 의미한다.  

이후 센티널은 다른 센티널 노드들에게 sentinel is-master-down-by-addr <master-ip> <master-port> <current-epoch> <*> 커맨드를 보내 마스터의 장애를 알린다.
위의 커맨드를 받은 세니널들은 해당 마스터 서버의 장애를 인지했는지 여부를 응답한다.  
자기 자신을 포함해 쿼럼 값 이상의 센티널 노드에서 마스터의 장애를 인지한다면 센티널 노드는 마스터의 상태를 odown으로 변경한다.  
odwon이란 objectly down, 즉 객관적인 다운 상태가 됐음을 의미한다.  

sentinel.log
+sdow
+odown




에포크 증가
처음으로 마스터 노드를 odwon으로 인지한 센티널 노드가 페일오버 과정을 시작한다.  
센티널은 페일오버를 시작하기 전 우선 에포크값을 하나 증가시킨다.  

센티널은 에포크라는 개념을 이용해 각 마스터에서 발생한 페일오버의 버전을 관리한다.
에포크는 증가하는 숫자값으로, 처음으로 페일오버가 일어날 때의 에포크 값은 1이 된다.  
새로운 페일오버가 발생할 때마다 에포크 값은 하나씩 증가하며, 동일한 에포크 값을 이용해 페일오버가 진행되는 동안 모든 센티널 노드가
같은 작업을 시도하고 있다는 것을 보장할 수 있다.

sentinel.log
+new-epoch 1
+try-failover 1

 

 


센티널 리더 선출
에포크를 증가시킨 센티널은 다른 센티널 노드에게 센티널 리더를 선출하기 위해 투표하라는 메시지를 보낸다.  
이때 증가시키 에포크를 함께 전달하는데 해당 메시지를 받은 센티널 노드가 현재 자신의 에포크보다 전달받은 에포크가 클 경우 자신의 에포크를 증가시킨 뒤,
센티널 리더에게 투표하겠다는 응답을 보낸다.
만약 센티널 노드가 투표받았을 경우 전달받은 에포크의 값이 자신의 에포크 값과 동일 하다면 이미 리더로 선출된 센티널의 id를 반환한다.  
하나의 에포크에서 센티널은 하나의 센티널에 투표할 수 있으며, 투표 결과는 변경할 수 없다.

sentinel.log
+vote-for-leader 1 1 1
+slected-leader 1 1 1



복제 선정 후 마스터로 승격
1. redis.conf 파일에 명시된 replica-priority가 낮은 복제본
2. 마슽로부터 더 많은 데이터를 수신한 복제본(master_repl_offset)
3. 2번 조건까지 동일하다면 runID가 사전 순으로 작은 복제본

작은 runID를 선택하는것에는 특별한 이유가 없으며 임의로 하나의 노드를 선택하는 방식이다.  

선정한 복제본은 slaveof no one 커맨드를 수행해 기존 마스터로부터의 복제본을 끊는다.

sentinel.log
+failover-state-select-slave 1
+selected-slave 1
+failover-state-send-slaveof-noone 1
+failover-state-wait-promotion 1
+promoted-slave 1



복제 연결 변경
기존 마스터에 연결돼 있던 다른 복제본이 새로 승격된 마스터의 복제본이 될 수 있도록 복제본마다 replicaof new-ip new-port 커맨드를 수행한다.  
복제 그룹의 모든 센티널 노드에서도 레디스의 구성 정보를 변경한다.

sentinel.log
+failover-state-reconf-slaves 1
+slave-reconf-sent
+slabe-reconf-inprog
+slave-reconf-done
+config-update-from sentinel



장애 조치 완료
모든 과정이 완료된 뒤 센티널은 새로운 마스터를 모니터링한다.

sentinel.log
+failover-end
+switch-master

 

 

 

스프링 부트 어플리케이션에서 센티널로 구축한 레디스와 통신하려면 RedisSentinelConfiguration 을 통해 센티널과 통신하면 된다.

마스터 - 슬레이브 관계에서 레디스는 마스터에만 쓰기 작업을 할 수 있어 센티널을 통해 마스터에 쓰고 읽는 작업을 수행하면 된다.

728x90

'DB' 카테고리의 다른 글

[MySQL] Index - 인덱스 사용법  (2) 2023.12.07
MySQL - 락과 격리 수준  (0) 2023.07.28
[DB] 함수(FUNCTUIN)  (0) 2022.08.23
[DB] 인덱스란?  (0) 2022.07.09
H2 데이터베이스 설정 초기화 하기  (0) 2022.05.08

댓글