Redis Cluster·Sentinel — 고가용성 한 번에

2026-05-02AWS SAA-C03 스터디

Redis 핵심 정리 시리즈 7편. Sentinel·Cluster를 사옥 안전 감시단·여러 동 분산 비유로 풀어가며 — 마스터-레플리카 복제, 자동 페일오버, 16384개 해시 슬롯, 해시 태그({}), 클러스터 노드 추가/제거, 메모리 정책(LRU·LFU), TLS·ACL·SLOWLOG, 장애 복구 시나리오, Docker Compose 구성까지 처음 보는 사람도 따라올 수 있게 친절하게 풀어쓴 7편.

📚 Redis 핵심 정리 · 7편 / 14편 — 고가용성 한 번에

이 글은 Redis 핵심 정리 시리즈의 일곱 번째 편입니다. 1~6편이 단일 Redis 서버 안에서의 이야기였다면, 7편은 본격적으로 여러 서버를 묶어 운영하는 영역으로 넘어갑니다. 이 단계에 오면 두 가지 개념이 큰 산처럼 등장해요 — Sentinel(고가용성)과 Cluster(수평 확장).

이 7편에서는 두 개념을 사옥 비유로 풀어 갑니다. Sentinel은 사옥 안전 감시단, Cluster는 사옥을 여러 동으로 나눠 데이터를 분산하는 구조예요. 둘은 해결하려는 문제도 다르고 적합한 자리도 다릅니다. 이 차이를 머리에 박아 두는 게 7편의 핵심이에요.

왜 Cluster·Sentinel이 처음엔 어렵게 느껴질까요

이유는 네 가지예요.

첫째, Sentinel과 Cluster의 차이가 한 번에 안 잡힙니다. 둘 다 "여러 서버"라는 이미지가 있어 비슷해 보이는데, 해결하려는 문제가 다릅니다. Sentinel은 "마스터가 죽으면 자동으로 새 마스터를 뽑는다", Cluster는 "데이터를 여러 서버에 쪼개 분산한다" — 이 구분이 처음엔 흐릿해요.

둘째, 숫자가 갑자기 많이 등장합니다. 16384개 슬롯, 5초 타임아웃, 26379 Sentinel 포트, 6379 Redis 포트, 최소 3개 Sentinel, 최소 6개 Cluster 노드 — 한 번에 외울 수 없는 숫자가 쏟아져요.

셋째, 마스터·레플리카·노드·슬롯 용어가 머리를 꼬이게 합니다. 같은 마스터인데 Sentinel 맥락에서는 "감시 대상", Cluster 맥락에서는 "슬롯 담당자"로 의미가 살짝 다릅니다.

넷째, 장애 시나리오가 머리에 안 그려져요. "마스터가 죽으면 페일오버" 같은 한 줄로는 실제로 어떤 단계로 어떻게 흘러가는지 시뮬레이션이 안 돼서, 운영 자신감이 안 붙습니다.

해결법은 한 가지예요. 사옥 비유를 두 갈래로 박아 두는 겁니다. Sentinel은 사옥 한 동을 24시간 지키는 안전 감시단, Cluster는 사옥 자체를 여러 동으로 쪼갠 캠퍼스 구조로 잡으면 갑자기 명확해집니다. 이 글은 그 비유를 따라 처음부터 풀어 갑니다.

단일 Redis 서버의 한계 — 왜 묶어야 할까요

단일 Redis 서버는 단순하고 빠르지만 두 가지 근본 문제가 있어요.

첫째, 서버가 다운되면 Redis를 쓰는 모든 서비스가 멈춥니다(SPOF, Single Point of Failure). 회사 비유로 — 사옥 한 채에 모든 직원이 모여 있는데 그 사옥이 정전되면 회사 전체가 멈추는 셈이에요.

둘째, 단일 서버 메모리 크기를 초과하는 데이터를 저장할 수 없어요. 사옥 한 채의 사물함 용량에 한계가 있는데 사물함을 더 늘릴 수 없어 곤란한 상황이죠.

단일 서버 문제:
  Redis 서버 다운 → 전체 서비스 중단 (SPOF)
  메모리 초과 → 저장 불가

해결책:
  복제(Replication): 고가용성 (HA, High Availability)
  클러스터링: 수평 확장 (Horizontal Scaling)

이 두 문제를 푸는 두 가지 도구가 복제(Replication)클러스터링(Clustering) 이에요. 차근차근 풀어 갑니다.

복제 — 마스터-레플리카 구조

Redis 복제(Replication) 는 하나의 마스터(Master)와 여러 레플리카(Replica)로 구성돼요. 마스터는 쓰기 작업을 처리하고, 레플리카는 마스터의 데이터를 실시간으로 복사합니다. 레플리카는 읽기 전용으로 사용해 읽기 부하를 분산할 수 있어요.

회사 비유로 — 본점이 있고 여러 분점이 있는 셈이에요. 본점(마스터) 에는 새 자료가 들어오면 등록하고, 분점(레플리카) 에는 본점에서 자료를 복사해 나눠 줍니다. 손님은 분점에서 자료를 조회만 할 수 있고(읽기 분산), 새 자료 등록은 항상 본점에 가서 해야 해요.

마스터 (M)  ──→  레플리카1 (R1)  [읽기 전용]
            ──→  레플리카2 (R2)  [읽기 전용]
            ──→  레플리카3 (R3)  [읽기 전용]

쓰기 → 마스터만 처리
읽기 → 마스터 또는 레플리카 선택 가능

복제 설정은 두 가지 방식이 있어요.

# 방법 1: redis.conf에서 설정
# 레플리카 서버의 설정 파일
replicaof 192.168.1.100 6379    # 마스터의 IP:PORT
masterauth your_master_password  # 마스터 인증 비밀번호

# 방법 2: redis-cli에서 런타임 설정
redis-cli -h replica-host REPLICAOF 192.168.1.100 6379

# 복제 상태 확인
redis-cli INFO replication
# role:master 또는 role:slave
# connected_slaves:2
# slave0:ip=192.168.1.101,port=6379,state=online

복제 동작 원리는 다음과 같아요.

초기 동기화:
  레플리카 연결 → 마스터가 RDB 스냅샷 생성 → 레플리카에 전송
  → 레플리카가 스냅샷 적용 → 이후 변경사항 실시간 스트리밍

지속적 동기화:
  마스터의 모든 쓰기 명령 → 레플리카에 비동기 전송
  레플리카 동기화 지연: 보통 < 10ms

여기서 시험 함정이 하나 있어요. 복제는 비동기입니다. 마스터가 쓰기를 받자마자 응답하고, 그 후에 레플리카로 전파해요. 그래서 레플리카에 즉시 반영되지 않은 시점에 마스터가 죽으면 일부 쓰기가 사라질 수 있습니다. 일관성이 절대적인 자리에는 별도 보강이 필요해요.

Sentinel — 사옥 안전 감시단

복제만 해두면 마스터가 죽었을 때 수동으로 레플리카를 새 마스터로 승격해야 합니다. 이걸 자동화하는 게 Redis Sentinel이에요.

Sentinel은 마스터와 레플리카를 지속적으로 모니터링하다가 마스터 장애를 감지하면 자동으로 레플리카를 새 마스터로 승격시켜요(Automatic Failover). 클라이언트는 Sentinel에 질의해 현재 마스터 주소를 알 수 있습니다.

회사 비유로 — Sentinel은 사옥을 24시간 지키는 안전 감시단이에요. 본점에 불이 나거나 정전이 되면 감시단들이 회의를 열어 "본점이 다운됐다"는 합의를 보고, 분점 중 하나를 새 본점으로 승격시킵니다. 그리고 모든 직원에게 새 본점 주소를 자동으로 알려요.

Sentinel 구성 (최소 3개 권장):
  Sentinel1 ─┐
  Sentinel2 ─┼─ 감시 → Master(M)
  Sentinel3 ─┘         ↓ 복제
                   Replica1(R1)
                   Replica2(R2)

마스터 장애 발생:
  Sentinel들이 마스터 다운 감지 (과반수 투표)
  → 레플리카 중 하나를 새 마스터로 선출
  → 다른 레플리카들이 새 마스터를 따름
  → 클라이언트에게 새 마스터 주소 알림

여기서 정말 중요한 시험 함정 — Sentinel은 최소 3개가 권장됩니다. 왜냐하면 페일오버 결정은 과반수 투표로 이뤄지기 때문이에요. 2개만 있으면 한 쪽이 다운되면 과반수가 안 만들어지고, 1개는 자기 자신이 죽으면 끝이라 의미가 없어요. 3개부터 의미 있는 합의가 가능합니다.

Sentinel 설정

# sentinel.conf
port 26379
sentinel monitor mymaster 192.168.1.100 6379 2
# mymaster: 모니터링할 마스터 이름
# 2: 마스터 다운 판단에 필요한 Sentinel 수 (과반수)

sentinel auth-pass mymaster your_password
sentinel down-after-milliseconds mymaster 5000   # 5초 이상 응답 없으면 다운으로 판단
sentinel failover-timeout mymaster 60000          # 페일오버 타임아웃 60초
sentinel parallel-syncs mymaster 1                # 한 번에 동기화할 레플리카 수

# Sentinel 시작
redis-sentinel /path/to/sentinel.conf
# 또는
redis-server /path/to/sentinel.conf --sentinel

Sentinel은 포트 26379를 표준으로 써요. 일반 Redis가 6379이고 그 앞에 2를 붙인 형태인데, 이 숫자도 시험에 자주 나옵니다.

자세한 설정과 동작은 Redis 공식 Sentinel 문서에서 확인할 수 있어요.

TypeScript에서 Sentinel 사용

import { createClient } from 'redis';

// Sentinel을 통한 Redis 연결
const client = createClient({
    sentinel: {
        sentinels: [
            { host: '192.168.1.101', port: 26379 },
            { host: '192.168.1.102', port: 26379 },
            { host: '192.168.1.103', port: 26379 },
        ],
        name: 'mymaster',  // sentinel.conf의 모니터링 이름
    },
    password: 'your_password',
});

await client.connect();

// 이후 일반 Redis 명령어 사용과 동일
// 페일오버 발생 시 자동으로 새 마스터에 재연결

클라이언트는 Sentinel 목록만 알면 됩니다. 마스터가 누구인지, 페일오버 됐는지는 Sentinel이 알려 줘요. 페일오버가 일어나도 클라이언트는 자동으로 새 마스터에 재연결됩니다.

Redis Cluster — 사옥을 여러 동으로 분산

Sentinel은 고가용성을 해결하지만 데이터 크기 제한은 못 풀어 줘요. 단일 마스터 RAM이 곧 데이터 한계니까요. 이걸 푸는 게 Redis Cluster입니다.

Cluster는 데이터를 여러 노드에 자동 분산(샤딩)해요. 단일 서버 메모리 한계를 넘어 수평 확장이 가능하고, 일부 노드가 다운돼도 다른 노드는 계속 서비스합니다.

회사 비유로 — Cluster는 사옥을 여러 동(棟)으로 쪼갠 캠퍼스 구조예요. 1동, 2동, 3동에 사물함을 분산 배치하고, 자료마다 어느 동에 보관할지 미리 정해 둡니다. 한 동이 정전돼도 다른 동은 계속 일할 수 있어요.

Redis Cluster (6노드: 마스터 3 + 레플리카 3):

  마스터1 (슬롯 0-5460)    ──→  레플리카1
  마스터2 (슬롯 5461-10922) ──→  레플리카2
  마스터3 (슬롯 10923-16383)──→  레플리카3

총 슬롯 수: 16384개
각 키는 해시 슬롯으로 매핑: slot = CRC16(key) % 16384

여기서 시험 함정이 하나 있어요. Cluster의 총 슬롯 수는 16384개입니다. 어떤 키든 CRC16(key) % 16384로 슬롯이 결정되고, 그 슬롯이 어느 마스터에 있는지에 따라 어느 노드에 저장될지 자동으로 결정돼요. 이 16384라는 숫자도 시험에 자주 나오는 단골입니다.

해시 슬롯과 키 분배

# 키의 해시 슬롯 계산
redis-cli CLUSTER KEYSLOT "user:1000"
# (integer) 7638  → 마스터2의 담당 슬롯

# 슬롯 분포 확인
redis-cli CLUSTER INFO
redis-cli CLUSTER NODES
redis-cli CLUSTER SLOTS

회사 비유로 — 자료 봉투에 이름을 적으면 그 이름의 해시값에 따라 자동으로 어느 동의 사물함에 갈지 결정되는 거예요. user:1000이라는 이름은 7638번 슬롯에 매핑되고, 그 슬롯을 담당하는 마스터로 자동 라우팅됩니다.

해시 태그 — 같은 동에 묶어 두기

여러 키를 같은 슬롯에 배치해야 하는 경우가 있어요. MULTI/EXEC 트랜잭션이나 MGET 같은 다중 키 명령어는 동일 슬롯의 키만 처리할 수 있기 때문이에요.

이 때 중괄호 {} 를 사용합니다. 중괄호 안의 내용으로만 슬롯을 계산하니, 같은 태그를 가진 키들은 모두 같은 슬롯으로 들어가요.

# 중괄호 안의 내용으로만 슬롯 계산
# user:1000:profile과 user:1000:settings를 같은 슬롯에 배치
CLUSTER KEYSLOT "{user:1000}.profile"   # user:1000으로 슬롯 계산
CLUSTER KEYSLOT "{user:1000}.settings"  # 동일한 슬롯

# 일반 키 vs 해시 태그 키
SET user:1000:profile "..."   # 슬롯: CRC16("user:1000:profile") % 16384
SET {user:1000}.profile "..."  # 슬롯: CRC16("user:1000") % 16384

회사 비유로 — {}"이 자료들은 같은 동에 모아 두라"는 라벨이에요. 한 사용자에 묶이는 자료(프로필·설정·세션)는 모두 같은 동에 보관해 두면 트랜잭션이나 다중 키 조회가 가능해집니다.

Cluster 설정

# redis.conf 설정
port 7001
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000        # 노드 타임아웃 5초
appendonly yes                   # AOF 활성화 권장

# 6개 인스턴스 시작 (7001~7006)
redis-server redis-7001.conf
redis-server redis-7002.conf
redis-server redis-7003.conf
redis-server redis-7004.conf
redis-server redis-7005.conf
redis-server redis-7006.conf

# 클러스터 생성 (--cluster-replicas 1: 각 마스터에 레플리카 1개)
redis-cli --cluster create \
    127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 \
    127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 \
    --cluster-replicas 1

# 클러스터 상태 확인
redis-cli --cluster check 127.0.0.1:7001
redis-cli -c CLUSTER INFO    # -c: 클러스터 모드 활성화

여기서 시험 함정이 하나 있어요. Cluster의 최소 노드 수는 6개입니다. 마스터 3개 + 각각의 레플리카 3개. 마스터가 3개 미만이면 페일오버 합의가 어려워지고, 레플리카가 없으면 마스터 다운 시 데이터를 잃어요.

자세한 클러스터 운영은 Redis 공식 scaling 문서에서 확인할 수 있어요.

TypeScript에서 Cluster 사용

import { createCluster } from 'redis';

const cluster = createCluster({
    rootNodes: [
        { url: 'redis://127.0.0.1:7001' },
        { url: 'redis://127.0.0.1:7002' },
        { url: 'redis://127.0.0.1:7003' },
    ],
    defaults: {
        password: 'your_password',
    },
});

await cluster.connect();

// 일반 명령어 사용 (자동으로 올바른 노드로 라우팅)
await cluster.set('user:1000', 'Alice');  // 자동으로 해당 슬롯의 마스터로 라우팅
const value = await cluster.get('user:1000');

// 해시 태그로 같은 노드에 배치
await cluster.set('{user:1000}.profile', profileData);
await cluster.set('{user:1000}.settings', settingsData);
// 이 두 키는 같은 노드에 저장됨 → MGET, 트랜잭션 가능

클러스터 운영 — 노드 추가/제거

운영 중에 데이터가 늘면 노드를 추가해 슬롯을 재분배해야 합니다.

# 새 마스터 노드 추가
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001
# 127.0.0.1:7007: 새 노드
# 127.0.0.1:7001: 기존 클러스터의 임의 노드

# 새 레플리카 노드 추가
redis-cli --cluster add-node --cluster-slave --cluster-master-id <master-id> \
    127.0.0.1:7008 127.0.0.1:7001

# 슬롯 재분배 (새 마스터에 슬롯 이동)
redis-cli --cluster rebalance 127.0.0.1:7001
# 또는 직접 슬롯 이동
redis-cli --cluster reshard 127.0.0.1:7001

노드 제거 시에는 슬롯을 다른 노드로 먼저 옮겨야 합니다. 슬롯이 남아 있는 채로 노드를 빼면 그 슬롯의 데이터에 접근할 수 없어져요.

# 노드 제거 전 슬롯을 다른 노드로 이동
redis-cli --cluster reshard --cluster-from <node-id> --cluster-to <other-node-id> \
    --cluster-slots <num-slots> 127.0.0.1:7001

# 슬롯이 없는 노드 제거
redis-cli --cluster del-node 127.0.0.1:7001 <node-id>

단일 / Sentinel / Cluster — 한눈에 비교

특성단일 서버SentinelCluster
고가용성XOO
자동 페일오버XOO
수평 확장XX (읽기만)O
최대 데이터RAM 크기단일 마스터 RAM노드 수 × RAM
다중 키 명령어OO제한적 (해시 태그 필요)
트랜잭션OO제한적 (같은 슬롯만)
설정 복잡도낮음중간높음
최소 노드 수13 (Sentinel) + 2 (마스터+레플리카)6
사용 사례개발/테스트, 소규모중소규모 HA대규모 확장

여기까지 따라오셨다면 한 가지 의문이 들 거예요. "그럼 어디까지 Sentinel로 가고, 어디부터 Cluster를 써야 하나?" — 정답은 데이터 크기가 가른다는 점입니다. 단일 서버 RAM(예: 64GB) 안에서 해결되면 Sentinel로 충분하고, 그걸 넘어가면 Cluster로 넘어가요.

메모리 관리 — maxmemory와 정책

운영 중인 Redis는 메모리 사용량을 항상 감시해야 합니다. 메모리가 가득 차면 어떻게 동작할지를 미리 정해 둬야 해요.

메모리 사용량 모니터링

# 전체 메모리 정보
redis-cli INFO memory

# 주요 지표:
# used_memory: 현재 사용 중인 메모리
# used_memory_rss: OS가 할당한 메모리 (단편화 포함)
# maxmemory: 설정된 최대 메모리
# mem_fragmentation_ratio: 메모리 단편화 비율 (1.5 이상이면 주의)

# 메모리 사용량이 많은 키 찾기
redis-cli --bigkeys

# 특정 키의 메모리 사용량
redis-cli MEMORY USAGE some-key
redis-cli MEMORY USAGE some-key SAMPLES 5

메모리 정책(Eviction Policy)

# redis.conf 또는 CONFIG SET
maxmemory 2gb
maxmemory-policy allkeys-lru

# 정책 종류:
# noeviction      : 메모리 한계 시 에러 반환 (기본값)
# allkeys-lru     : 모든 키 중 가장 오래 사용 안 한 키 삭제
# volatile-lru    : TTL 있는 키 중 LRU 삭제
# allkeys-random  : 모든 키 중 무작위 삭제
# volatile-random : TTL 있는 키 중 무작위 삭제
# volatile-ttl    : TTL이 가장 짧은 키부터 삭제
# allkeys-lfu     : 사용 빈도가 낮은 키 삭제 (Redis 4.0+)
# volatile-lfu    : TTL 있는 키 중 사용 빈도가 낮은 키 삭제

여기서 시험 함정이 하나 있어요. 기본값은 noeviction 으로, 메모리가 가득 차면 쓰기에 에러를 반환합니다. 캐시 용도라면 거의 무조건 allkeys-lru 또는 allkeys-lfu 로 바꿔 두는 게 안전해요. LRU(가장 오래 안 쓴 것 먼저)와 LFU(가장 적게 쓴 것 먼저)는 자주 비교에 등장합니다.

메모리 최적화 기법

# Hash, List, Set의 인코딩 최적화
# 데이터가 작을 때 압축된 형식 사용 (ziplist/listpack)
hash-max-listpack-entries 128   # Hash를 ziplist로 저장하는 최대 필드 수
hash-max-listpack-value 64      # 최대 필드 값 크기 (bytes)

zset-max-listpack-entries 128
zset-max-listpack-value 64

list-max-listpack-size -2       # 최대 8kb의 ziplist

set-max-intset-entries 512      # 정수만 있는 Set의 intset 크기

보안 — TLS·ACL·방화벽

운영 환경의 Redis는 반드시 보안 설정을 거쳐야 합니다. Redis는 기본적으로 빠른 동작을 우선하기 때문에, 보안은 운영자가 직접 챙겨야 해요.

TLS/SSL 설정

# redis.conf TLS 설정
tls-port 6380
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-auth-clients yes    # 클라이언트 인증서 요구

# TLS 연결
redis-cli -h localhost -p 6380 --tls \
    --cert /etc/redis/tls/client.crt \
    --key /etc/redis/tls/client.key \
    --cacert /etc/redis/tls/ca.crt

ACL — 사용자별 세밀한 권한 관리

Redis 6.0부터는 ACL(Access Control List) 로 사용자별 권한을 관리할 수 있어요. 각 사용자에게 특정 명령어나 키 패턴 접근 권한을 따로 부여할 수 있습니다.

# ACL 사용자 생성
ACL SETUSER alice on >password123 ~users:* &* +get +set +del
# on: 활성화
# >password123: 비밀번호 설정
# ~users:*: users: 로 시작하는 키만 접근 허용
# &*: 모든 채널 구독/발행 허용
# +get +set +del: GET, SET, DEL 명령어 허용

# 읽기 전용 사용자
ACL SETUSER readonly on >readpass ~* +@read -@write

# ACL 목록 조회
ACL LIST
ACL WHOAMI    # 현재 사용자 확인
ACL CAT       # 명령어 카테고리 목록

# redis.conf에서 ACL 파일 지정
aclfile /etc/redis/users.acl

회사 비유로 — ACL은 출입증마다 어느 층, 어느 사물함, 어떤 작업이 가능한지 따로 부여하는 시스템이에요. 운영자는 어드민 권한, 모니터링 시스템은 읽기 전용, 배치 잡은 특정 키 패턴만 — 이렇게 분리할 수 있습니다.

방화벽 설정

# Redis는 기본적으로 모든 인터페이스에서 수신
# redis.conf에서 특정 인터페이스만 바인딩
bind 127.0.0.1 192.168.1.100   # 로컬 및 내부 IP만

# 보호 모드 활성화 (기본값)
protected-mode yes

# 비밀번호 설정
requirepass your_strong_password

모니터링 — INFO·SLOWLOG·CLIENT

운영 자신감은 모니터링에서 나와요. 자주 쓰는 명령어 4종을 정리합니다.

INFO 명령어

# 전체 정보
redis-cli INFO

# 섹션별 조회
redis-cli INFO server      # 서버 정보
redis-cli INFO clients     # 연결된 클라이언트
redis-cli INFO memory      # 메모리 사용
redis-cli INFO stats       # 통계 (히트율, 요청 수)
redis-cli INFO replication # 복제 상태
redis-cli INFO cpu         # CPU 사용량
redis-cli INFO keyspace    # DB별 키 정보

MONITOR — 실시간 명령어 추적

# 실시간 명령어 모니터링 (개발/디버깅 전용, 운영 환경 주의)
redis-cli MONITOR
# 모든 명령어가 실시간으로 출력됨
# 성능에 영향을 주므로 운영 환경에서는 짧게 사용

여기서 시험 함정이 하나 있어요. MONITOR는 운영 환경에서 오래 켜두면 안 됩니다. 모든 명령어를 실시간 출력하느라 성능이 크게 떨어져요. 디버깅 목적으로 짧게(수 초~수십 초) 켰다가 끄는 게 정답입니다.

SLOWLOG — 느린 쿼리 추적

# 느린 쿼리 로깅 설정
redis-cli CONFIG SET slowlog-log-slower-than 10000  # 10ms 이상인 명령어 기록
redis-cli CONFIG SET slowlog-max-len 128             # 최대 128개 기록

# 느린 쿼리 조회
redis-cli SLOWLOG GET 10    # 최근 10개
redis-cli SLOWLOG LEN       # 총 레코드 수
redis-cli SLOWLOG RESET     # 초기화

성능 문제 진단할 때 가장 먼저 보는 명령이에요. Redis는 단일 스레드라 한 명령이 오래 걸리면 그 동안 다른 명령이 대기합니다. SLOWLOG로 누가 시간을 잡아먹고 있는지를 빠르게 잡아낼 수 있어요.

CLIENT 명령어

# 연결된 클라이언트 목록
redis-cli CLIENT LIST

# 특정 클라이언트 이름 설정
redis-cli CLIENT SETNAME my-app-server

# 유휴 클라이언트 종료
redis-cli CLIENT KILL ID <client-id>
redis-cli CLIENT KILL ADDR 192.168.1.101:54321

# 클라이언트 수 제한
redis-cli CONFIG SET maxclients 10000

장애 복구 시나리오

마스터 장애 (Sentinel)

회사 비유로 — 본점이 정전됐을 때 안전 감시단들이 어떤 단계로 새 본점을 뽑는지 한 줄씩 따라가 보면 다음과 같아요.

시나리오: 마스터 서버 다운

1. Sentinel들이 마스터 ping 실패 감지
2. 5초 후 (down-after-milliseconds) "주관적 다운(SDOWN)" 판정
3. 과반수 Sentinel 동의 시 "객관적 다운(ODOWN)" 판정
4. 리더 Sentinel 선출 (Raft 알고리즘)
5. 가장 적합한 레플리카 선출 (복제 우선순위, 복제 오프셋 등 기준)
6. 선출된 레플리카를 새 마스터로 승격
7. 나머지 레플리카들이 새 마스터를 따르도록 재구성
8. 클라이언트에게 새 마스터 주소 알림 (+switch-master 이벤트)

용어가 두 단어 등장해요 — SDOWN(주관적 다운)은 한 Sentinel이 보기에 다운, ODOWN(객관적 다운)은 과반수 Sentinel이 동의한 다운입니다. SDOWN만으로는 페일오버가 일어나지 않아요. ODOWN까지 가야 새 마스터 선출이 시작됩니다.

클러스터 노드 장애

시나리오: 클러스터 마스터 노드 다운

1. 다른 노드들이 gossip 프로토콜로 장애 감지
2. cluster-node-timeout(기본 15초) 후 PFAIL(possible failure) 판정
3. 과반수 마스터 동의 시 FAIL 판정
4. 해당 마스터의 레플리카가 새 마스터로 선출
5. 슬롯 재매핑 완료

주의: 모든 슬롯이 서빙 가능한 상태여야 클러스터가 정상 동작
     레플리카 없는 마스터 장애 시 클러스터 전체 서비스 중단

여기서 정말 중요한 시험 함정 — 레플리카 없는 마스터가 다운되면 클러스터 전체가 중단됩니다. 그 마스터가 담당하던 슬롯에 데이터가 사라져 버리기 때문이에요. 그래서 운영에서는 모든 마스터에 레플리카를 최소 1개씩 두는 게 표준입니다.

데이터 복구

# RDB 파일에서 복구
# dump.rdb를 Redis 데이터 디렉토리에 복사 후 재시작
cp /backup/dump-20231101.rdb /var/lib/redis/dump.rdb
redis-server redis.conf

# AOF 파일 복구
redis-check-aof --fix appendonly.aof    # 손상된 AOF 파일 복구
redis-server --appendonly yes           # AOF 복구 모드로 시작

영속성 전략(RDB·AOF)는 4편에서 자세히 다뤘어요. 운영 환경에서는 두 가지를 함께 쓰는 하이브리드가 표준입니다.

Docker Compose로 복제 환경 구성

로컬에서 마스터-레플리카-Sentinel 환경을 띄워 실험하고 싶다면 Docker Compose로 1분 만에 가능해요.

# docker-compose.yml
version: '3.8'
services:
  redis-master:
    image: redis:7
    ports:
      - "6379:6379"
    command: redis-server --requirepass password123
    
  redis-replica1:
    image: redis:7
    ports:
      - "6380:6379"
    command: redis-server --replicaof redis-master 6379 --masterauth password123 --requirepass password123
    depends_on:
      - redis-master
      
  redis-replica2:
    image: redis:7
    ports:
      - "6381:6379"
    command: redis-server --replicaof redis-master 6379 --masterauth password123 --requirepass password123
    depends_on:
      - redis-master
      
  redis-sentinel:
    image: redis:7
    ports:
      - "26379:26379"
    command: >
      redis-sentinel /sentinel.conf
    volumes:
      - ./sentinel.conf:/sentinel.conf
    depends_on:
      - redis-master
      - redis-replica1
      - redis-replica2

운영에서 자주 보는 함정 5가지

1. 단일 슬롯 제약 위반 — 다중 키 명령어

# 잘못된 방법: 클러스터에서 다중 키 명령어 (다른 슬롯)
MSET user:1 "Alice" user:2 "Bob"
# CROSSSLOT Keys in request don't hash to the same slot 에러!

# 올바른 방법 1: 해시 태그 사용
MSET {user}:1 "Alice" {user}:2 "Bob"   # {user}로 슬롯 통일

# 올바른 방법 2: 각각 개별 명령어로
SET user:1 "Alice"
SET user:2 "Bob"

2. Sentinel vs Cluster 혼동

Sentinel: 고가용성 전용 (자동 페일오버)
          → 단일 마스터의 데이터 크기 제한은 해결 안 됨
          → 읽기 분산만 가능

Cluster: 수평 확장 (샤딩) + 고가용성
         → 데이터를 여러 노드에 분산
         → 다중 키 명령어 제한 있음

3. Cluster에서 Lua 스크립트 주의

-- 클러스터에서는 Lua 스크립트의 모든 키가 같은 슬롯에 있어야 함
-- 잘못된 방법: 다른 슬롯의 키 접근
redis.call('GET', KEYS[1])  -- user:1 → 슬롯 1000
redis.call('GET', KEYS[2])  -- item:1 → 슬롯 2000 (에러!)

-- 올바른 방법: 해시 태그로 같은 슬롯 보장
-- {tag}:user:1 과 {tag}:item:1 모두 "tag"의 슬롯으로 계산

4. 메모리 단편화 문제

# mem_fragmentation_ratio 확인
redis-cli INFO memory | grep mem_fragmentation_ratio
# 1.0: 정상
# 1.5 이상: 단편화 심각
# 1.0 미만: 스왑 사용 중 (매우 나쁨)

# 단편화 해소 (Redis 4.0+)
redis-cli MEMORY PURGE

# 또는 재시작을 통한 메모리 정리
# 이 경우 RDB/AOF 설정 확인 필요

여기서 시험 함정이 하나 있어요. mem_fragmentation_ratio가 1.0 미만이면 스왑 사용 중이라는 신호로, 매우 나쁜 상황입니다. RAM이 모자라 OS가 디스크 스왑을 쓰고 있다는 뜻이에요. Redis 성능 폭락의 주범입니다.

5. 네트워크 지연으로 인한 잘못된 페일오버

# Sentinel down-after-milliseconds를 너무 짧게 설정하면
# 일시적 네트워크 지연을 장애로 오판하여 불필요한 페일오버 발생

# 권장: 5000ms 이상 (5초)
sentinel down-after-milliseconds mymaster 5000

# 운영 환경에서는 15000~30000ms를 권장하는 경우도 있음

회사 비유로 — 안전 감시단이 너무 예민하면 본점에서 잠깐 무전이 끊겼을 뿐인데 "본점 다운"으로 판정하고 새 본점을 뽑아 버려요. 그러면 진짜 본점은 멀쩡한데 분점이 새 본점이 되는 헷갈리는 상황이 생깁니다. 타임아웃은 너무 짧지도 너무 길지도 않게 잡는 게 핵심이에요.

시험 직전 한 번 더 — 자주 헷갈리는 함정 모음

여기까지가 Redis 7편(Cluster·고가용성)의 핵심입니다. 시험 직전·실무 실수 방지를 위한 압축 노트로 마무리할게요.

  • 단일 서버 한계 두 가지 — SPOF(단일 장애점) + 메모리 크기 제한
  • 해결 두 갈래 — 복제(Replication) = HA, 클러스터(Clustering) = 수평 확장
  • 마스터-레플리카 — 마스터만 쓰기, 레플리카는 읽기 전용 (읽기 분산)
  • 복제는 비동기 — 마스터 다운 시 일부 쓰기 손실 가능
  • Sentinel = 사옥 안전 감시단 — 마스터 다운 자동 감지·페일오버
  • Sentinel 최소 3개, 페일오버는 과반수 투표
  • Sentinel 포트 = 26379 (Redis는 6379)
  • SDOWN(주관적 다운, 한 Sentinel만) → ODOWN(객관적 다운, 과반수 동의)
  • 페일오버 단계 — Ping 실패 → SDOWN → ODOWN → 리더 Sentinel 선출 → 새 마스터 선출 → 재구성
  • Cluster = 사옥 여러 동으로 분산 — 수평 확장 + HA
  • 총 슬롯 수 = 16384개, 슬롯 = CRC16(key) % 16384
  • Cluster 최소 6노드 (마스터 3 + 레플리카 3)
  • 다중 키 명령어 (MGET·MSET·트랜잭션) — 같은 슬롯에서만 가능
  • 해시 태그 {} — 중괄호 안 내용으로만 슬롯 계산, 같은 슬롯에 묶을 때
  • 단일 vs Sentinel vs Cluster — 데이터 크기·HA 요구·복잡도가 결정
  • maxmemory-policy — 캐시 용도라면 allkeys-lru 또는 allkeys-lfu
  • 기본값 noeviction — 캐시 운영에는 위험 (메모리 가득 차면 쓰기 에러)
  • LRU vs LFU — 가장 오래 안 쓴 것 vs 가장 적게 쓴 것
  • TLS·ACL·bind·requirepass — 운영 보안 4종 세트
  • ACL — Redis 6.0+, 사용자별 키 패턴·명령어 권한 따로
  • MONITOR 운영에서 길게 켜면 성능 폭락 — 디버깅 짧게만
  • SLOWLOG — 느린 쿼리 진단 1순위 도구
  • mem_fragmentation_ratio 1.0 미만 = 스왑 사용 중 (매우 나쁨)
  • 레플리카 없는 마스터 다운 = 클러스터 전체 중단 — 모든 마스터에 레플리카 1개+
  • Sentinel down-after-milliseconds 너무 짧으면 불필요한 페일오버 발생 (5초+ 권장)
  • 자주 헷갈리는 비교 — Sentinel vs Cluster = HA 전용 vs HA + 수평 확장
  • 자주 헷갈리는 비교 — 노드 추가 vs 슬롯 재분배 = 추가만으로는 부족, reshard 필요

시리즈 다른 편

같은 시리즈의 다른 글들도 같은 친절 톤으로 묶어 정리되어 있어요.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!