Redis Sentinel: SDOWN

Redis 단일 인스턴스의 한계: 왜 고가용성이 필요한가

Redis를 단일 인스턴스로 운영하면 해당 노드가 다운되는 순간 전체 서비스가 캐시 없이 동작하거나, 세션/큐 데이터가 유실됩니다. 이를 해결하기 위해 Redis는 두 가지 고가용성 솔루션을 제공합니다:

솔루션 목적 데이터 분산 자동 페일오버
Redis Sentinel 고가용성 (HA) 없음 (단일 마스터)
Redis Cluster 수평 확장 + HA 있음 (16384 해시 슬롯)

이 아티클에서는 Redis Sentinel에 집중합니다. 데이터가 단일 마스터에 수용 가능한 규모(수십 GB 이하)이고, 수평 분산보다 자동 페일오버와 운영 단순성이 중요한 환경에서 Sentinel이 적합합니다.

Sentinel의 세 가지 역할

Redis Sentinel은 독립 프로세스로 실행되며 세 가지 핵심 기능을 수행합니다:

  1. 모니터링(Monitoring): 마스터와 레플리카가 정상 동작하는지 주기적으로 확인합니다.
  2. 알림(Notification): 모니터링 중 이상이 감지되면 관리자에게 알리거나 스크립트를 실행합니다.
  3. 자동 페일오버(Automatic Failover): 마스터가 다운되면 레플리카 중 하나를 새 마스터로 승격시키고, 나머지 레플리카와 클라이언트에게 새 마스터를 알립니다.
                ┌──────────┐  ┌──────────┐  ┌──────────┐
                │Sentinel 1│  │Sentinel 2│  │Sentinel 3│
                └────┬─────┘  └────┬─────┘  └────┬─────┘
                     │             │              │
          ┌──────────┴─────────────┴──────────────┴───────┐
          │                                               │
     ┌────▼────┐           ┌──────────┐           ┌──────────┐
     │ Master  │──복제────▶│Replica 1 │           │Replica 2 │
     │ :6379   │──복제────▶│ :6380    │           │ :6381    │
     └─────────┘           └──────────┘           └──────────┘

최소 구성: Sentinel 3대가 필요한 이유

Sentinel은 과반수 합의(quorum)로 페일오버를 결정합니다. Sentinel 2대로 운영하면 네트워크 파티션 시 과반수를 확보할 수 없어 페일오버가 불가능합니다.

Sentinel 수 quorum (최소) 허용 장애 수 권장 여부
1 1 0 (SPOF) ❌ 사용 금지
2 2 0 (과반수 불가) ❌ 부족
3 2 1 ✅ 최소 권장
5 3 2 ✅ 높은 안정성

핵심 규칙: Sentinel 수는 항상 홀수로 설정합니다. quorum은 ceil(N/2)로 설정하는 것이 일반적입니다.

Sentinel 설정 파일

# sentinel.conf

# Sentinel 자체 포트
port 26379

# 모니터링할 마스터 정의
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 10.0.0.1 6379 2

# 마스터가 응답하지 않으면 SDOWN 판정 (밀리초)
sentinel down-after-milliseconds mymaster 5000

# 페일오버 후 새 마스터에 동시 동기화할 레플리카 수
sentinel parallel-syncs mymaster 1

# 페일오버 타임아웃 (밀리초)
sentinel failover-timeout mymaster 60000

# Redis 인증 (마스터/레플리카에 requirepass 설정 시)
# sentinel auth-pass mymaster your-redis-password

# Sentinel 간 인증 (Sentinel도 보호할 때)
# requirepass sentinel-password

핵심 파라미터 설명

파라미터 기본값 설명
down-after-milliseconds 30000 (30초) 이 시간 동안 PING 응답이 없으면 SDOWN (주관적 다운)
parallel-syncs 1 페일오버 후 동시에 새 마스터와 동기화하는 레플리카 수. 높으면 빠르지만 동기화 중 레플리카 서비스 불가
failover-timeout 180000 (3분) 페일오버 전체 과정의 타임아웃. 이 시간 초과 시 다른 Sentinel이 재시도

페일오버 과정: SDOWN → ODOWN → 투표 → 승격

마스터 장애 시 Sentinel의 페일오버는 4단계로 진행됩니다:

1단계: SDOWN (Subjectively Down)

개별 Sentinel이 down-after-milliseconds 동안 마스터에서 응답을 받지 못하면, 해당 Sentinel은 마스터를 주관적으로 다운이라 판단합니다. 이 시점에서는 아직 페일오버가 시작되지 않습니다.

2단계: ODOWN (Objectively Down)

SDOWN을 감지한 Sentinel이 다른 Sentinel에게 확인을 요청합니다. quorum 이상의 Sentinel이 마스터가 다운되었다고 동의하면 ODOWN(객관적 다운) 상태로 전환됩니다.

3단계: 리더 선출

Sentinel들 중 하나가 페일오버를 주도할 리더로 선출됩니다. Raft 알고리즘 변형을 사용하며, 과반수의 투표가 필요합니다.

4단계: 레플리카 승격

리더 Sentinel이 최적의 레플리카를 선택하여 새 마스터로 승격합니다. 선택 기준:

  • replica-priority: 낮을수록 우선 (0은 승격 불가)
  • replication offset: 높을수록 우선 (데이터가 더 최신)
  • Run ID: 사전순으로 작은 것 우선 (동점 처리)
# 페일오버 과정 모니터링
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
# 1) "10.0.0.1"
# 2) "6379"

# 마스터 다운 후 다시 확인
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
# 1) "10.0.0.2"    ← 새 마스터로 변경됨
# 2) "6380"

클라이언트 연결: Sentinel을 통한 마스터 디스커버리

Sentinel 환경에서 클라이언트는 마스터의 IP:Port를 직접 지정하지 않고, Sentinel에게 현재 마스터를 질의하여 연결합니다. 이렇게 해야 페일오버 후 새 마스터로 자동 전환됩니다.

Node.js (ioredis)

import Redis from 'ioredis';

const redis = new Redis({
  sentinels: [
    { host: '10.0.0.10', port: 26379 },
    { host: '10.0.0.11', port: 26379 },
    { host: '10.0.0.12', port: 26379 },
  ],
  name: 'mymaster',         // sentinel monitor에서 설정한 마스터 이름
  // password: 'redis-password',       // Redis 인증
  // sentinelPassword: 'sentinel-pw',  // Sentinel 인증
  db: 0,
  retryStrategy(times) {
    return Math.min(times * 200, 5000);  // 재연결 백오프
  },
});

Spring Boot (Lettuce)

# application.yml
spring:
  data:
    redis:
      sentinel:
        master: mymaster
        nodes:
          - 10.0.0.10:26379
          - 10.0.0.11:26379
          - 10.0.0.12:26379
      # password: redis-password
      timeout: 5000ms

NestJS (BullMQ)

// BullMQ + Sentinel 연결
BullModule.forRoot({
  connection: {
    sentinels: [
      { host: '10.0.0.10', port: 26379 },
      { host: '10.0.0.11', port: 26379 },
      { host: '10.0.0.12', port: 26379 },
    ],
    name: 'mymaster',
    maxRetriesPerRequest: null,  // BullMQ 필수
  },
})

읽기 분산: 레플리카 읽기 설정

Sentinel 환경에서 쓰기는 반드시 마스터로 가지만, 읽기는 레플리카로 분산할 수 있습니다.

// ioredis: preferredSlaves로 읽기 분산
const redis = new Redis({
  sentinels: [...],
  name: 'mymaster',
  role: 'slave',              // 레플리카에 연결
  preferredSlaves: [
    { ip: '10.0.0.2', port: '6380', prio: 1 },
  ],
});

주의: 레플리카 읽기는 비동기 복제 지연으로 인해 약간의 stale 데이터를 읽을 수 있습니다. 강한 일관성이 필요한 조회(결제 상태, 재고 확인)는 반드시 마스터에서 읽어야 합니다.

Sentinel 명령어 레퍼런스

# Sentinel 접속
redis-cli -p 26379

# 모니터링 중인 마스터 정보
SENTINEL masters

# 특정 마스터의 상세 정보
SENTINEL master mymaster

# 마스터의 레플리카 목록
SENTINEL replicas mymaster

# 다른 Sentinel 목록
SENTINEL sentinels mymaster

# 현재 마스터 주소
SENTINEL get-master-addr-by-name mymaster

# 수동 페일오버 트리거 (운영 점검 시)
SENTINEL failover mymaster

# 마스터가 정상인데 강제로 재설정
SENTINEL reset mymaster

주요 명령어 비교

명령어 용도 사용 시점
SENTINEL masters 모든 마스터 상태 확인 일상 모니터링
SENTINEL replicas 레플리카 상태·오프셋 확인 복제 지연 진단
SENTINEL failover 수동 페일오버 계획된 마스터 점검 시
SENTINEL reset 마스터 감시 재설정 레플리카 추가/제거 후 정리

Sentinel 이벤트와 알림 스크립트

Sentinel은 페일오버 등 주요 이벤트 발생 시 외부 스크립트를 실행할 수 있습니다.

# sentinel.conf
sentinel notification-script mymaster /opt/redis/notify.sh
sentinel client-reconfig-script mymaster /opt/redis/reconfig.sh
#!/bin/bash
# /opt/redis/notify.sh — 페일오버 알림
# 인수: <event-type> <event-description>
EVENT_TYPE=$1
EVENT_DESC=$2

curl -s -X POST "https://hooks.slack.com/services/xxx" 
  -H 'Content-Type: application/json' 
  -d "{"text":"[Redis Sentinel] ${EVENT_TYPE}: ${EVENT_DESC}"}"
#!/bin/bash
# /opt/redis/reconfig.sh — 페일오버 완료 후 실행
# 인수: <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
MASTER_NAME=$1
ROLE=$2
NEW_IP=$6
NEW_PORT=$7

echo "$(date) Failover: ${MASTER_NAME} new master is ${NEW_IP}:${NEW_PORT}" 
  >> /var/log/redis/failover.log

Sentinel vs Cluster: 선택 기준

기준 Redis Sentinel Redis Cluster
데이터 규모 단일 마스터에 수용 가능 (수십 GB) 수백 GB 이상, 수평 분산 필요
쓰기 처리량 단일 마스터의 처리량 여러 마스터에 분산
운영 복잡성 낮음 높음 (해시 슬롯, 리샤딩)
MULTI/EXEC 제한 없음 같은 슬롯 키만 가능
Lua 스크립트 제한 없음 같은 슬롯 키만 접근 가능
Pub/Sub 정상 동작 모든 노드에 브로드캐스트 (비효율)
최소 Redis 인스턴스 3 (1 master + 2 replica) 6 (3 master + 3 replica)

판단 기준: 데이터가 단일 노드 메모리에 수용 가능하고, MULTI/EXEC·Lua 스크립트를 자유롭게 사용해야 한다면 Sentinel. 데이터가 단일 노드를 초과하거나 쓰기 처리량 분산이 필요하면 Cluster를 선택합니다.

운영 함정과 Best Practice

  1. Sentinel을 Redis 서버와 같은 노드에 배치하지 마세요: Redis 서버가 죽으면 Sentinel도 함께 죽어 quorum을 확보할 수 없습니다. Sentinel은 별도 노드 또는 애플리케이션 서버에 배치합니다.
  2. down-after-milliseconds를 너무 낮게 설정하지 마세요: 네트워크 일시적 지연으로 불필요한 페일오버가 발생합니다. 프로덕션에서는 5000~10000ms가 적절합니다.
  3. parallel-syncs = 1 유지: 이 값을 높이면 여러 레플리카가 동시에 새 마스터와 전체 동기화를 시작하여, 동기화 중 읽기 서비스가 불가능한 레플리카가 늘어납니다.
  4. min-replicas-to-write 설정: 마스터에 min-replicas-to-write 1min-replicas-max-lag 10을 설정하면, 레플리카가 모두 다운되었을 때 마스터가 쓰기를 거부하여 데이터 유실을 줄입니다.
  5. NAT/Docker 환경 주의: Sentinel은 Redis INFO 명령으로 레플리카의 IP를 파악합니다. NAT 뒤에 있으면 내부 IP가 노출되어 클라이언트가 연결하지 못합니다. replica-announce-ipsentinel announce-ip를 명시적으로 설정하세요.
# redis.conf (마스터/레플리카)
min-replicas-to-write 1        # 최소 1개 레플리카 연결 시만 쓰기 허용
min-replicas-max-lag 10        # 레플리카 복제 지연 10초 이내

# Docker/NAT 환경
replica-announce-ip 203.0.113.10
replica-announce-port 6379

# sentinel.conf — Docker/NAT 환경
sentinel announce-ip 203.0.113.20
sentinel announce-port 26379

운영 모니터링 체크리스트

모니터링 항목 확인 방법 임계값
Sentinel quorum 유지 SENTINEL ckquorum mymaster OK 응답이어야 함
마스터 상태 SENTINEL master mymaster의 flags “master”만 표시
레플리카 복제 지연 INFO replication의 lag 10초 이하
페일오버 횟수 SENTINEL master mymaster의 num-other-sentinels, failover-count 비정상적 증가 시 알림
Sentinel 간 연결 SENTINEL sentinels mymaster 모든 Sentinel이 조회되어야 함

핵심 정리

  • Sentinel은 3대 이상 홀수로 배포하고, quorum은 과반수로 설정합니다.
  • 페일오버는 SDOWN → ODOWN → 리더 선출 → 레플리카 승격 4단계로 진행되며, 전체 과정은 보통 수 초 내 완료됩니다.
  • 클라이언트는 Sentinel을 통해 마스터를 디스커버리해야 페일오버 시 자동 전환됩니다. IP를 직접 지정하면 안 됩니다.
  • min-replicas-to-write를 설정하여 네트워크 파티션 시 데이터 유실을 줄이세요.
  • 데이터 규모가 단일 마스터를 초과하거나 쓰기 분산이 필요하면 Redis Cluster로 전환을 검토합니다.

참고 자료

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux