홈시리즈

© 2026 Ki Chang. All rights reserved.

본 블로그의 콘텐츠는 CC BY-NC-SA 4.0 라이선스를 따릅니다.

☕후원하기소개JSON Formatter러닝 대기질개인정보처리방침이용약관

© 2026 Ki Chang. All rights reserved.

콘텐츠: CC BY-NC-SA 4.0

☕후원하기
소개|JSON Formatter|러닝 대기질|개인정보처리방침|이용약관

Redis Sentinel vs Cluster — 고가용성 아키텍처의 선택 기준

정기창·2026년 3월 12일

단일 노드의 한계

Redis를 단일 노드로 운영하면, 그 노드가 죽는 순간 Redis에 의존하는 모든 것이 멈춥니다. 캐시가 사라지고, Bull Queue가 멈추고, 세션이 날아가고, 분산 락이 작동하지 않습니다.

Redis는 이 문제를 해결하기 위해 세 가지 레벨의 고가용성을 제공합니다. Replication(복제), Sentinel(감시자), Cluster(분산). 각각은 이전 단계 위에 구축되므로, 순서대로 이해하는 것이 중요합니다.

1단계: Replication — 데이터 복제의 기초

모든 고가용성의 출발점은 데이터를 여러 곳에 복사해두는 것입니다.

동작 원리

┌──────────┐     비동기 복제     ┌──────────────┐
│  Master  │ ──────────────────→ │  Replica #1  │
│  (읽기+  │                     └──────────────┘
│   쓰기)  │ ──────────────────→ ┌──────────────┐
└──────────┘                     │  Replica #2  │
                                 └──────────────┘
  • Master: 모든 쓰기 명령을 처리합니다
  • Replica: Master의 데이터를 복제하며, 읽기 요청을 처리할 수 있습니다
  • 비동기 복제: Master에 쓰기 → Master가 OK 반환 → 이후에 Replica에 전파. Replica에 도달하기 전에 Master가 죽으면 그 데이터는 유실됩니다

복제 과정

1. 초기 동기화 (Full Sync):
   Replica → Master: "PSYNC ? -1" (처음 연결)
   Master: fork() → RDB 생성 → Replica에 전송
   Master: RDB 생성 중 들어온 명령도 버퍼에 쌓아서 전송
   Replica: RDB 로드 + 버퍼 명령 실행 → 동기화 완료

2. 이후 증분 동기화 (Partial Sync):
   Master → Replica: 실시간으로 쓰기 명령 전파
   (replication backlog 버퍼에 최근 명령 보관)

3. 네트워크 끊김 후 재연결:
   Replica → Master: "PSYNC repl_id offset"
   Master: backlog에 있으면 → 부분 동기화 (빠름)
   Master: backlog에 없으면 → 전체 동기화 (느림)

한계

Replication만으로는 자동 장애 복구(failover)가 없습니다. Master가 죽으면 누군가가 수동으로 Replica를 승격해야 합니다. 새벽 3시에 Master가 죽으면, 운영자가 일어나서 REPLICAOF NO ONE을 실행해야 합니다. 이것이 Sentinel이 필요한 이유입니다.

2단계: Sentinel — 자동 장애 복구

Sentinel은 Redis 인스턴스들을 모니터링하다가, Master가 죽으면 자동으로 Replica를 새 Master로 승격하는 시스템입니다.

아키텍처

┌────────────┐  ┌────────────┐  ┌────────────┐
│ Sentinel 1 │  │ Sentinel 2 │  │ Sentinel 3 │
└─────┬──────┘  └─────┬──────┘  └─────┬──────┘
      │               │               │
      │          모니터링              │
      ▼               ▼               ▼
┌──────────┐     ┌──────────────┐  ┌──────────────┐
│  Master  │ ──→ │  Replica #1  │  │  Replica #2  │
└──────────┘     └──────────────┘  └──────────────┘

Sentinel은 별도의 프로세스로, 최소 3대 이상 운영해야 합니다. 과반수 합의로 결정을 내리기 때문입니다.

Failover 과정

1. 장애 감지 (SDOWN → ODOWN):
   Sentinel 1: Master에 PING → 응답 없음 (down-after-milliseconds 초과)
   → SDOWN (Subjectively Down) — 나 혼자 판단

   Sentinel 1 → Sentinel 2, 3에 확인 요청
   과반수(2/3)가 동의 → ODOWN (Objectively Down) — 객관적 판단

2. 리더 선출 (Raft 기반):
   Sentinel들 중 하나가 failover를 주도할 리더로 선출됨
   (과반수 투표 필요)

3. Replica 선택:
   리더 Sentinel이 가장 적합한 Replica 선택
   기준: replica-priority → 복제 오프셋(최신 데이터) → Run ID

4. 승격:
   선택된 Replica에 REPLICAOF NO ONE → 새 Master
   나머지 Replica에 REPLICAOF 새_Master_IP 포트
   클라이언트에 새 Master 주소 알림

전체 소요 시간: 보통 5~15초

클라이언트 연결

Sentinel 환경에서 클라이언트는 Master에 직접 연결하지 않습니다. Sentinel에게 "현재 Master가 누구인지" 물어보고, 그 주소로 연결합니다.

// ioredis (Node.js) 예시
const redis = new Redis({
  sentinels: [
    { host: 'sentinel-1', port: 26379 },
    { host: 'sentinel-2', port: 26379 },
    { host: 'sentinel-3', port: 26379 },
  ],
  name: 'mymaster',  // Sentinel이 모니터링하는 마스터 이름
});

Failover가 발생하면 ioredis 같은 라이브러리가 Sentinel의 +switch-master 이벤트를 받아 자동으로 새 Master에 재연결합니다.

Sentinel의 한계

  • 수직 확장만 가능: 모든 데이터가 하나의 Master에 있으므로, 메모리가 부족하면 더 큰 서버가 필요합니다
  • 쓰기 확장 불가: 쓰기는 Master 한 대에서만 처리됩니다
  • 비동기 복제로 인한 데이터 유실: Failover 시 아직 복제되지 않은 쓰기가 유실될 수 있습니다

데이터가 한 서버 메모리에 충분히 들어가고, 쓰기 부하가 한 대로 감당 가능하다면 Sentinel이 가장 단순하고 안정적인 선택입니다.

3단계: Cluster — 샤딩 + 고가용성

데이터가 한 서버 메모리를 넘어가거나, 쓰기 부하를 분산해야 할 때 Cluster가 필요합니다.

해시 슬롯: 데이터 분산의 원리

Redis Cluster는 키 공간을 16,384개의 해시 슬롯으로 나눕니다. 각 마스터 노드가 슬롯의 일부를 담당합니다.

슬롯 할당 예시 (3 Master):
Master A: 슬롯 0 ~ 5460
Master B: 슬롯 5461 ~ 10922
Master C: 슬롯 10923 ~ 16383

키 → 슬롯 매핑:
HASH_SLOT = CRC16(key) mod 16384

"user:1001" → CRC16("user:1001") mod 16384 → 슬롯 7238 → Master B
"session:abc" → CRC16("session:abc") mod 16384 → 슬롯 2847 → Master A

클라이언트가 잘못된 노드에 명령을 보내면, 그 노드가 MOVED 응답으로 올바른 노드를 알려줍니다.

Client → Master A: GET user:1001
Master A → Client: -MOVED 7238 192.168.1.2:6379
Client → Master B: GET user:1001
Master B → Client: "John"

Cluster의 Failover

Cluster에서는 Sentinel 없이 노드끼리 자체적으로 failover를 수행합니다. 각 마스터 노드마다 하나 이상의 Replica를 두고, 마스터가 죽으면 해당 Replica가 자동 승격됩니다.

┌──────────┐  ┌──────────┐  ┌──────────┐
│ Master A │  │ Master B │  │ Master C │
│ 0~5460   │  │ 5461~    │  │ 10923~   │
└─────┬────┘  └─────┬────┘  └─────┬────┘
      │             │             │
      ▼             ▼             ▼
┌──────────┐  ┌──────────┐  ┌──────────┐
│Replica A1│  │Replica B1│  │Replica C1│
└──────────┘  └──────────┘  └──────────┘

Master B 장애 시:
1. 다른 Master들이 Master B의 PING 실패 감지
2. 과반수가 동의하면 Master B를 PFAIL → FAIL 상태로 전환
3. Replica B1이 자동으로 새 Master B로 승격
4. 슬롯 5461~10922는 이제 Replica B1(새 Master)이 담당

멀티키 명령의 제약

Cluster의 가장 큰 제약은 여러 키에 걸친 명령이 제한된다는 것입니다. 다른 슬롯에 있는 키끼리는 트랜잭션(MULTI/EXEC), 파이프라이닝, Lua 스크립트에서 함께 쓸 수 없습니다.

MGET user:1001 user:1002  → 같은 슬롯이면 OK, 다르면 CROSSSLOT 에러

이 문제를 해결하기 위해 Hash Tag를 사용합니다. 키 이름에 {}로 감싼 부분만 해시 계산에 사용됩니다.

user:{1001}:profile  → CRC16("1001") → 같은 슬롯
user:{1001}:session  → CRC16("1001") → 같은 슬롯
→ 같은 유저의 데이터를 같은 노드에 모을 수 있음

하지만 Hash Tag를 과도하게 사용하면 특정 슬롯에 데이터가 편중되어 샤딩의 이점이 사라집니다. 설계 시 주의가 필요합니다.

노드 추가와 리밸런싱

Cluster에 노드를 추가하거나 제거할 때, 해시 슬롯이 재분배됩니다.

기존: A(0~5460), B(5461~10922), C(10923~16383)

Master D 추가:
→ A, B, C에서 각각 슬롯 일부를 D로 이동
→ A(0~4095), B(5461~9556), C(10923~15017), D(나머지)
→ 슬롯 이동 중에도 클라이언트 요청 처리 가능 (ASK 리다이렉션)

슬롯 마이그레이션 중에는 ASK 리다이렉션으로 일시적으로 양쪽 노드에 요청이 분산됩니다. 마이그레이션이 완료되면 MOVED로 최종 노드를 안내합니다.

Sentinel vs Cluster: 비교 요약

항목SentinelCluster
데이터 분산X (단일 Master)O (해시 슬롯 샤딩)
수평 확장XO
자동 FailoverOO
별도 프로세스Sentinel 3대+불필요 (자체 관리)
멀티키 명령제한 없음같은 슬롯만 가능
클라이언트 복잡도Sentinel 주소 필요Cluster 프로토콜 필요
최대 메모리단일 서버 한계노드 수 × 서버 메모리
쓰기 확장X (Master 1대)O (Master N대)
운영 복잡도낮음높음
최소 노드 수Redis 3 + Sentinel 3Master 3 + Replica 3

실무 선택 기준

어떤 아키텍처를 선택할지는 두 가지 질문으로 결정됩니다.

질문 1: 데이터가 한 서버 메모리에 들어가는가?

Redis 인스턴스의 maxmemory를 보통 서버 메모리의 60~70%로 설정합니다. 32GB 서버라면 약 20GB. 데이터가 이 범위 안에 들어가면 Sentinel로 충분합니다.

질문 2: 쓰기 처리량이 단일 노드 한계를 넘는가?

단일 Redis 노드는 초당 10만~50만 건의 명령을 처리합니다. 이 수준을 넘는 쓰기 부하가 있다면 Cluster로 분산해야 합니다.

조건추천 아키텍처
데이터 < 단일 서버 메모리 && 쓰기 부하 < 단일 노드 한계Sentinel (단순하고 안정적)
데이터 > 단일 서버 메모리 || 쓰기 부하 > 단일 노드 한계Cluster (수평 확장 필요)
데이터 유실 감수 가능 && 자동 failover 불필요Replication만 (가장 단순)
Redis를 순수 캐시로만 사용Cluster (캐시 샤딩) 또는 Sentinel (규모에 따라)

주의: Cluster는 만능이 아닙니다

Cluster가 더 좋아 보인다고 무조건 선택하면 안 됩니다. 운영 복잡도가 높고, 멀티키 명령 제약으로 인해 애플리케이션 코드 변경이 필요할 수 있습니다. Lua 스크립트도 같은 슬롯 내에서만 동작합니다. 기존에 MGET, MULTI/EXEC, Lua 스크립트를 많이 쓰고 있다면, Cluster로 전환 시 코드 수정 범위를 먼저 파악해야 합니다.

비동기 복제의 근본적 한계

Sentinel이든 Cluster든, Redis의 복제는 기본적으로 비동기입니다. 이것은 failover 시 데이터 유실 가능성이 항상 존재한다는 뜻입니다.

1. Client → Master: SET important_data "value" → OK
2. Master 크래시 (Replica에 아직 복제 안 됨)
3. Failover → Replica가 새 Master로 승격
4. important_data는 유실됨

Redis에는 WAIT 명령으로 동기 복제를 일부 흉내낼 수 있지만, 완전한 동기 복제는 아닙니다. 절대적인 데이터 정합성이 필요하다면 Redis가 아닌 합의 기반 시스템(etcd, ZooKeeper)이나 RDBMS의 동기 복제를 고려해야 합니다.

정리

Redis의 고가용성은 Replication → Sentinel → Cluster 순으로 기능이 추가됩니다. 각 단계는 이전 단계의 한계를 해결하지만, 동시에 새로운 복잡성을 더합니다.

실무에서 가장 중요한 것은 "지금 우리에게 무엇이 필요한가"를 정확히 아는 것입니다. 데이터가 작고 쓰기가 적다면 Sentinel로 충분합니다. "나중에 커지면 어쩌지"라는 걱정으로 Cluster를 선택하면, 불필요한 운영 복잡도만 떠안게 됩니다. 필요해질 때 전환해도 늦지 않습니다.

RedisSentinelCluster고가용성샤딩Replication면접 준비

관련 글

Redis 내부 원리 총정리 — 싱글 스레드부터 클러스터까지

Redis를 캐시로만 쓰다가 면접에서 "싱글 스레드인데 왜 빠른가?"라는 질문에 막힌 경험이 있습니다. 싱글 스레드 모델, 자료구조별 시간복잡도, RDB/AOF 영속성, 메모리 관리, Sentinel과 Cluster까지 — Redis 내부 원리를 한 글에 정리했습니다.

관련도 91%

Redis가 싱글 스레드인데 왜 빠른가 — I/O 멀티플렉싱부터 6.0 스레드 모델까지

Redis가 싱글 스레드라는 말은 반만 맞습니다. 정확히 무엇이 싱글 스레드이고, I/O 멀티플렉싱은 어떻게 동작하며, Redis 6.0의 I/O 스레드는 무엇을 바꿨는지. 면접에서 "왜 빠른가?"에 확실히 답할 수 있도록 정리했습니다.

관련도 89%

Redis 영속성 전략 — RDB vs AOF, 그리고 혼합 방식의 트레이드오프

Redis는 인메모리 데이터베이스이지만, 데이터를 디스크에 저장하는 두 가지 방식이 있습니다. RDB 스냅샷의 fork()와 COW 메커니즘, AOF의 fsync 정책, 그리고 Redis 4.0의 혼합 방식까지. 실무 선택 기준을 정리했습니다.

관련도 89%