Sentinel — 자동 페일오버와 고가용성
Redis 마스터가 갑자기 죽으면 누가 레플리카를 마스터로 승격시켜야 할까요? 수동으로요?
개념 정의
Redis Sentinel 은 마스터를 모니터링하다가 장애를 감지하면 자동으로 레플리카를 마스터로 승격(페일오버)하는 고가용성(HA) 솔루션 입니다. 페일오버 후 다른 레플리카와 클라이언트에게 새 마스터 정보를 자동으로 알려줍니다.
왜 필요한가
- Replication만으로는 마스터 장애 시 레플리카가 **자동으로 승격되지 않습니다 **. 사람이 직접
REPLICAOF NO ONE을 실행해야 합니다. - 사람이 개입해야 하기 때문에 새벽 3시에 장애가 나면 대응까지 ** 수 분~수십 분 **이 걸립니다.
- 따라서 Sentinel이 자동으로 장애를 감지하고 페일오버를 수행하여 ** 무중단에 가까운 운영 **을 가능하게 합니다.
Sentinel의 세 가지 역할
- ** 모니터링(Monitoring)**: 마스터와 레플리카가 정상 동작하는지 주기적으로 확인
- ** 알림(Notification)**: 장애 발생 시 관리자에게 알림 (스크립트 실행 등)
- ** 자동 페일오버(Automatic Failover)**: 마스터 장애 시 레플리카를 자동으로 승격
기본 구성
최소 구성 (3 Sentinel + 1 Master + 2 Replica)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Sentinel #1 │ │ Sentinel #2 │ │ Sentinel #3 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└────────┬───────┴────────┬───────┘
│ │
┌──────┴──────┐ ┌─────┴───────┐
│ Master │ │ Replica 1 │
└─────────────┘ └─────────────┘
┌─────────────┐
│ Replica 2 │
└─────────────┘
sentinel.conf 설정
# 기본 설정
port 26379
sentinel monitor mymaster 192.168.1.100 6379 2
# mymaster: 마스터 이름
# 192.168.1.100 6379: 마스터 주소
# 2: 쿼럼 (페일오버에 동의해야 하는 Sentinel 수)
sentinel monitor의 마지막 숫자가 쿼럼입니다. 이 수 이상의 Sentinel이 마스터 다운에 동의해야 페일오버가 시작됩니다.
# 다운 판정 시간 (밀리초)
sentinel down-after-milliseconds mymaster 5000
# 5초간 응답 없으면 SDOWN
# 페일오버 타임아웃
sentinel failover-timeout mymaster 60000
# 동시에 새 마스터로 동기화하는 레플리카 수
sentinel parallel-syncs mymaster 1
# 인증
sentinel auth-pass mymaster "마스터비밀번호"
Sentinel 실행
# 방법 1
redis-sentinel /path/to/sentinel.conf
# 방법 2
redis-server /path/to/sentinel.conf --sentinel
장애 감지 과정
1단계: SDOWN (Subjectively Down)
Sentinel → PING → Master
← 응답 없음 (down-after-milliseconds 초과)
→ 이 Sentinel이 마스터를 SDOWN으로 표시
(주관적 판단 — 이 Sentinel만의 의견)
2단계: ODOWN (Objectively Down)
SDOWN을 감지한 Sentinel이 다른 Sentinel에게 확인:
"마스터가 다운된 것 같은데, 너희도 그렇게 보여?"
쿼럼(예: 2) 이상이 동의하면 → ODOWN (객관적 다운)
3단계: Sentinel Leader 선출
ODOWN이 확정되면 페일오버를 실행할 리더를 선출
- Raft 유사 알고리즘으로 과반수 동의 필요
- 리더만 페일오버를 실행
자동 페일오버 과정
1. Sentinel Leader가 레플리카 중 하나를 선택
선택 기준 (우선순위 순):
- replica-priority가 낮은 것 (0은 제외)
- 복제 오프셋이 가장 큰 것 (최신 데이터)
- run_id가 가장 작은 것 (타이브레이커)
2. 선택된 레플리카에 REPLICAOF NO ONE 실행 → 마스터로 승격
3. 다른 레플리카에 REPLICAOF <new-master> 실행
→ 새 마스터를 바라보도록 변경
4. 기존 마스터가 복구되면 새 마스터의 레플리카로 편입
replica-priority 설정
# 레플리카 설정
replica-priority 100 # 기본값
# 0으로 설정하면 마스터로 승격 대상에서 제외
replica-priority 0 # 백업 전용 레플리카 등
클라이언트 연결
클라이언트는 마스터의 IP를 직접 지정하지 않고, Sentinel을 통해 현재 마스터를 조회합니다.
Sentinel 명령어
# 현재 마스터 주소 조회
127.0.0.1:26379> SENTINEL GET-MASTER-ADDR-BY-NAME mymaster
1) "192.168.1.101" # 페일오버 후 새 마스터 IP
2) "6380"
# 마스터 정보 조회
127.0.0.1:26379> SENTINEL MASTER mymaster
# 레플리카 정보 조회
127.0.0.1:26379> SENTINEL REPLICAS mymaster
# Sentinel 목록 조회
127.0.0.1:26379> SENTINEL SENTINELS mymaster
Spring Boot 연결
# application.yml
spring:
data:
redis:
sentinel:
master: mymaster
nodes:
- sentinel1:26379
- sentinel2:26379
- sentinel3:26379
password: sentinel-password
password: redis-password
@Configuration
public class RedisSentinelConfig {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisSentinelConfiguration sentinelConfig =
new RedisSentinelConfiguration()
.master("mymaster")
.sentinel("sentinel1", 26379)
.sentinel("sentinel2", 26379)
.sentinel("sentinel3", 26379);
sentinelConfig.setPassword("redis-password");
return new LettuceConnectionFactory(sentinelConfig);
}
}
Lettuce와 Jedis 모두 Sentinel을 통한 자동 마스터 디스커버리를 지원합니다. 페일오버가 발생하면 클라이언트 라이브러리가 자동으로 새 마스터에 연결합니다.
스플릿 브레인 (Split Brain) 문제
시나리오
정상 상태:
[Sentinel1] [Sentinel2] [Sentinel3]
| | |
[Master] [Replica1] [Replica2]
네트워크 분할:
파티션 A 파티션 B
[Sentinel1] [Sentinel2] [Sentinel3]
[Master] ← 쓰기 계속 받음 | |
[Replica1] ← 새 마스터로 승격
→ 두 개의 마스터가 동시에 쓰기를 받음!
→ 네트워크 복구 후 기존 Master의 데이터 유실
대응 방법
# 마스터 측 설정 — 레플리카가 부족하면 쓰기 거부
min-replicas-to-write 1
min-replicas-max-lag 10
# 이렇게 하면 고립된 마스터는 쓰기를 거부
# 파티션 A의 기존 마스터: 레플리카 0개 → 쓰기 거부
# 파티션 B의 새 마스터: 레플리카 1개 → 쓰기 허용
Sentinel 알림 스크립트
# sentinel.conf
sentinel notification-script mymaster /path/to/notify.sh
sentinel client-reconfig-script mymaster /path/to/reconfig.sh
#!/bin/bash
# notify.sh — 장애 알림
# 인자: <event_type> <event_description>
echo "Redis 장애: $1 - $2" | mail -s "Redis Alert" admin@example.com
#!/bin/bash
# reconfig.sh — 페일오버 후 재설정
# 인자: <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
echo "마스터 변경: $4:$5 → $6:$7"
# DNS 업데이트, 로드밸런서 재설정 등
Sentinel 운영 팁
쿼럼과 과반수
3 Sentinel, 쿼럼 2:
- ODOWN 판정: 2개 동의 필요
- 리더 선출: 과반수(2개) 동의 필요
- 1대 장애 허용
5 Sentinel, 쿼럼 3:
- ODOWN 판정: 3개 동의 필요
- 리더 선출: 과반수(3개) 동의 필요
- 2대 장애 허용
Sentinel 배치 원칙
- Sentinel은 Redis 서버와 같은 머신에 배치하지 않는 것이 이상적
- 서로 다른 가용 영역(AZ)에 분산 배치
- 짝수 개는 피하기 (합의 불가능 상황 발생)
페일오버 테스트
# 강제 페일오버 트리거
127.0.0.1:26379> SENTINEL FAILOVER mymaster
# 마스터를 의도적으로 중단
redis-cli -p 6379 DEBUG SLEEP 30 # 30초 동안 응답 중단
함정/Pitfall
1. Sentinel 2대로 운영하면 페일오버가 안 될 수 있다
Sentinel은 리더 선출에 ** 과반수** 동의가 필요합니다. 2대 중 1대가 죽으면 남은 1대로는 과반수를 충족할 수 없어 페일오버가 불가능합니다. 반드시 3대 이상을 홀수로 배포하세요.
2. 스플릿 브레인으로 데이터가 유실될 수 있다
네트워크 파티션이 발생하면 기존 마스터와 새로 승격된 마스터가 동시에 쓰기를 받을 수 있습니다. 네트워크 복구 후 기존 마스터가 새 마스터의 레플리카로 편입되면서 ** 파티션 동안 받은 쓰기가 유실 **됩니다. min-replicas-to-write를 설정하면 고립된 마스터가 쓰기를 거부하여 유실 범위를 줄일 수 있습니다.
3. down-after-milliseconds를 너무 짧게 설정하면 불필요한 페일오버가 발생한다
네트워크가 일시적으로 느려지거나 GC pause가 발생했을 때 마스터가 정상인데도 SDOWN으로 잘못 판정될 수 있습니다. 프로덕션에서는 5초(5000ms) 이상으로 설정하는 것이 일반적입니다.
Sentinel vs Cluster
| 특성 | Sentinel | Cluster |
|---|---|---|
| 목적 | 고가용성 (페일오버) | 수평 확장 + 고가용성 |
| 샤딩 | 없음 | 해시 슬롯 기반 |
| 데이터 분산 | 모든 노드에 전체 데이터 | 노드별로 다른 데이터 |
| 적합한 경우 | 데이터가 단일 노드에 들어갈 때 | 데이터가 단일 노드 용량 초과 시 |
정리
| 항목 | 핵심 내용 |
|---|---|
| 역할 | 마스터 모니터링 + 자동 페일오버 + 클라이언트 알림 |
| 장애 감지 | SDOWN(주관적) → ODOWN(쿼럼 합의) → 리더 선출 → 페일오버 |
| 배포 원칙 | 최소 3대 홀수, 서로 다른 장애 도메인에 분산 |
| 스플릿 브레인 | min-replicas-to-write로 고립된 마스터 쓰기 거부 |
| 클라이언트 | Sentinel을 통해 자동 마스터 디스커버리, 수동 개입 불필요 |