Skip to content

필사 모드: Redis Cluster 구축과 운영 실전 가이드 — 샤딩, 레플리케이션, 페일오버

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며

단일 Redis 인스턴스는 메모리와 처리량에 한계가 있습니다. **Redis Cluster**는 데이터를 여러 노드에 자동으로 분산(샤딩)하고, 노드 장애 시 자동 페일오버를 제공하는 네이티브 클러스터링 솔루션입니다.

이 글에서는 Redis Cluster의 아키텍처를 이해하고, 실제 구축부터 운영까지 단계별로 살펴봅니다.

Redis Cluster 아키텍처

해시 슬롯 (Hash Slots)

Redis Cluster는 **16,384개의 해시 슬롯**을 사용하여 데이터를 분산합니다:

키의 해시 슬롯 계산

HASH_SLOT = CRC16(key) % 16384

예시: 3개 마스터 노드

Node A: 슬롯 0 ~ 5460

Node B: 슬롯 5461 ~ 10922

Node C: 슬롯 10923 ~ 16383

클러스터 토폴로지

최소 권장 구성: 3 Master + 3 Replica = 6 노드

#

Master A (슬롯 0-5460) ←→ Replica A'

Master B (슬롯 5461-10922) ←→ Replica B'

Master C (슬롯 10923-16383) ←→ Replica C'

#

각 Master가 다운되면 해당 Replica가 자동 승격

6노드 Redis Cluster 구축

Docker Compose로 구축

docker-compose.yml

version: '3.8'

services:

redis-node-1:

image: redis:7.4

container_name: redis-node-1

ports:

- '7001:7001'

- '17001:17001'

volumes:

- ./redis-node-1:/data

command: >

redis-server

--port 7001

--cluster-enabled yes

--cluster-config-file nodes.conf

--cluster-node-timeout 5000

--appendonly yes

--protected-mode no

--bind 0.0.0.0

networks:

redis-cluster:

ipv4_address: 172.20.0.11

redis-node-2:

image: redis:7.4

container_name: redis-node-2

ports:

- '7002:7002'

- '17002:17002'

volumes:

- ./redis-node-2:/data

command: >

redis-server

--port 7002

--cluster-enabled yes

--cluster-config-file nodes.conf

--cluster-node-timeout 5000

--appendonly yes

--protected-mode no

--bind 0.0.0.0

networks:

redis-cluster:

ipv4_address: 172.20.0.12

redis-node-3:

image: redis:7.4

container_name: redis-node-3

ports:

- '7003:7003'

- '17003:17003'

volumes:

- ./redis-node-3:/data

command: >

redis-server

--port 7003

--cluster-enabled yes

--cluster-config-file nodes.conf

--cluster-node-timeout 5000

--appendonly yes

--protected-mode no

--bind 0.0.0.0

networks:

redis-cluster:

ipv4_address: 172.20.0.13

redis-node-4:

image: redis:7.4

container_name: redis-node-4

ports:

- '7004:7004'

- '17004:17004'

volumes:

- ./redis-node-4:/data

command: >

redis-server

--port 7004

--cluster-enabled yes

--cluster-config-file nodes.conf

--cluster-node-timeout 5000

--appendonly yes

--protected-mode no

--bind 0.0.0.0

networks:

redis-cluster:

ipv4_address: 172.20.0.14

redis-node-5:

image: redis:7.4

container_name: redis-node-5

ports:

- '7005:7005'

- '17005:17005'

volumes:

- ./redis-node-5:/data

command: >

redis-server

--port 7005

--cluster-enabled yes

--cluster-config-file nodes.conf

--cluster-node-timeout 5000

--appendonly yes

--protected-mode no

--bind 0.0.0.0

networks:

redis-cluster:

ipv4_address: 172.20.0.15

redis-node-6:

image: redis:7.4

container_name: redis-node-6

ports:

- '7006:7006'

- '17006:17006'

volumes:

- ./redis-node-6:/data

command: >

redis-server

--port 7006

--cluster-enabled yes

--cluster-config-file nodes.conf

--cluster-node-timeout 5000

--appendonly yes

--protected-mode no

--bind 0.0.0.0

networks:

redis-cluster:

ipv4_address: 172.20.0.16

networks:

redis-cluster:

driver: bridge

ipam:

config:

- subnet: 172.20.0.0/24

컨테이너 시작

docker compose up -d

클러스터 생성 (3 master + 3 replica)

docker exec -it redis-node-1 redis-cli --cluster create \

172.20.0.11:7001 172.20.0.12:7002 172.20.0.13:7003 \

172.20.0.14:7004 172.20.0.15:7005 172.20.0.16:7006 \

--cluster-replicas 1 --cluster-yes

클러스터 상태 확인

docker exec -it redis-node-1 redis-cli -p 7001 cluster info

docker exec -it redis-node-1 redis-cli -p 7001 cluster nodes

베어메탈/VM에서 구축

Redis 설치 (Ubuntu)

sudo apt update && sudo apt install -y redis-server

노드별 설정 파일 생성

cat > /etc/redis/redis-7001.conf << 'EOF'

port 7001

cluster-enabled yes

cluster-config-file nodes-7001.conf

cluster-node-timeout 5000

appendonly yes

appendfilename "appendonly-7001.aof"

dbfilename dump-7001.rdb

dir /var/lib/redis/7001

logfile /var/log/redis/redis-7001.log

pidfile /var/run/redis/redis-7001.pid

protected-mode no

bind 0.0.0.0

메모리 설정

maxmemory 4gb

maxmemory-policy allkeys-lru

성능 튜닝

tcp-backlog 511

timeout 0

tcp-keepalive 300

EOF

디렉토리 생성

sudo mkdir -p /var/lib/redis/7001

sudo chown redis:redis /var/lib/redis/7001

서비스 시작

sudo redis-server /etc/redis/redis-7001.conf --daemonize yes

6개 노드 모두 시작 후 클러스터 생성

redis-cli --cluster create \

192.168.1.1:7001 192.168.1.2:7002 192.168.1.3:7003 \

192.168.1.4:7004 192.168.1.5:7005 192.168.1.6:7006 \

--cluster-replicas 1

클러스터 운영

데이터 읽기/쓰기

클러스터 모드로 접속 (-c 플래그)

redis-cli -c -h 172.20.0.11 -p 7001

MOVED 리다이렉션 자동 처리

172.20.0.11:7001> SET user:1000 "Kim Youngju"

-> Redirected to slot [3817] located at 172.20.0.11:7001

OK

172.20.0.11:7001> SET user:2000 "Park Minho"

-> Redirected to slot [8234] located at 172.20.0.12:7002

OK

Hash Tag로 같은 슬롯에 저장

{user:1000} 부분만 해시 계산에 사용됨

SET {user:1000}.profile "Kim Youngju"

SET {user:1000}.email "youngju@example.com"

SET {user:1000}.settings "{\"theme\":\"dark\"}"

같은 슬롯에 저장되므로 MGET 가능

MGET {user:1000}.profile {user:1000}.email

Python 클라이언트

from redis.cluster import RedisCluster

클러스터 연결

rc = RedisCluster(

startup_nodes=[

{"host": "172.20.0.11", "port": 7001},

{"host": "172.20.0.12", "port": 7002},

{"host": "172.20.0.13", "port": 7003},

],

decode_responses=True,

skip_full_coverage_check=True

)

기본 작업

rc.set("user:1000", "Kim Youngju")

print(rc.get("user:1000"))

파이프라인 (같은 슬롯의 키만)

pipe = rc.pipeline()

pipe.set("{user:1000}.name", "Kim Youngju")

pipe.set("{user:1000}.age", "30")

pipe.get("{user:1000}.name")

results = pipe.execute()

print(results)

클러스터 정보

print(rc.cluster_info())

노드 추가/제거

새 마스터 노드 추가

redis-cli --cluster add-node 172.20.0.17:7007 172.20.0.11:7001

슬롯 리밸런싱

redis-cli --cluster rebalance 172.20.0.11:7001

새 노드에 레플리카 추가

redis-cli --cluster add-node 172.20.0.18:7008 172.20.0.11:7001 \

--cluster-slave --cluster-master-id <master-node-id>

노드 제거 (먼저 슬롯을 다른 노드로 이동)

redis-cli --cluster reshard 172.20.0.11:7001 \

--cluster-from <removing-node-id> \

--cluster-to <target-node-id> \

--cluster-slots 5461 \

--cluster-yes

redis-cli --cluster del-node 172.20.0.11:7001 <removing-node-id>

자동 페일오버

페일오버 동작 과정

1. Master A 다운 감지 (cluster-node-timeout 초 후)

2. Replica A'가 다른 Master들에게 투표 요청

3. 과반수 Master가 승인하면 Replica A'가 Master로 승격

4. 새 Master A'가 기존 슬롯 담당

페일오버 테스트

docker stop redis-node-1

상태 확인 (Replica가 Master로 승격됨)

docker exec -it redis-node-2 redis-cli -p 7002 cluster nodes

수동 페일오버

Replica에서 실행 (graceful failover)

redis-cli -h 172.20.0.14 -p 7004 CLUSTER FAILOVER

강제 페일오버 (Master가 다운된 경우)

redis-cli -h 172.20.0.14 -p 7004 CLUSTER FAILOVER FORCE

모니터링

핵심 메트릭

클러스터 상태 확인

redis-cli -p 7001 cluster info

cluster_state:ok

cluster_slots_assigned:16384

cluster_slots_ok:16384

cluster_known_nodes:6

노드별 메모리 사용량

redis-cli -p 7001 info memory

used_memory_human:1.5G

maxmemory_human:4.0G

슬롯 분배 확인

redis-cli --cluster check 172.20.0.11:7001

Prometheus + Grafana 모니터링

docker-compose.monitoring.yml

services:

redis-exporter:

image: oliver006/redis_exporter:latest

environment:

- REDIS_ADDR=redis://172.20.0.11:7001

- REDIS_CLUSTER=true

ports:

- '9121:9121'

prometheus.yml

scrape_configs:

- job_name: 'redis-cluster'

static_configs:

- targets: ['redis-exporter:9121']

주요 Grafana 대시보드 쿼리

초당 명령 수

rate(redis_commands_processed_total[5m])

메모리 사용률

redis_memory_used_bytes / redis_memory_max_bytes * 100

키 수

redis_db_keys

연결된 클라이언트 수

redis_connected_clients

복제 지연

redis_replication_offset

트러블슈팅

CROSSSLOT 에러

에러: CROSSSLOT Keys in request don't hash to the same slot

원인: MGET, MSET 등에서 다른 슬롯의 키를 사용

해결: Hash Tag 사용

MGET {order:1}.items {order:1}.total # OK (같은 슬롯)

MGET order:1 order:2 # ERROR (다른 슬롯 가능)

클러스터 상태 복구

클러스터 상태가 fail인 경우

redis-cli --cluster fix 172.20.0.11:7001

슬롯이 누락된 경우

redis-cli --cluster fix 172.20.0.11:7001 --cluster-fix-with-unreachable-masters

마무리

Redis Cluster 운영의 핵심:

1. **최소 6노드**: 3 Master + 3 Replica로 고가용성 확보

2. **Hash Tag 활용**: 관련 키를 같은 슬롯에 배치

3. **자동 페일오버**: cluster-node-timeout 설정에 따라 자동 복구

4. **리샤딩**: 노드 추가/제거 시 슬롯 재분배

5. **모니터링**: Prometheus + redis_exporter로 상시 감시

**Q1. Redis Cluster의 해시 슬롯 개수는?**

16,384개

**Q2. 키의 해시 슬롯을 계산하는 공식은?**

CRC16(key) % 16384

**Q3. Hash Tag의 역할은?**

중괄호 안의 문자열만 해시 계산에 사용하여 관련 키를 같은 슬롯에 배치

**Q4. 자동 페일오버 시 Replica가 Master로 승격되려면?**

과반수 Master의 투표(승인)가 필요

**Q5. CROSSSLOT 에러의 원인과 해결법은?**

다른 슬롯의 키를 한 명령에서 사용할 때 발생. Hash Tag로 같은 슬롯에 배치하여 해결

**Q6. cluster-node-timeout의 역할은?**

노드 장애를 감지하는 시간. 이 시간 동안 응답이 없으면 장애로 판단

**Q7. 노드 제거 시 먼저 해야 하는 작업은?**

해당 노드의 슬롯을 다른 노드로 리샤딩(reshard)

현재 단락 (1/253)

단일 Redis 인스턴스는 메모리와 처리량에 한계가 있습니다. **Redis Cluster**는 데이터를 여러 노드에 자동으로 분산(샤딩)하고, 노드 장애 시 자동 페일오버를 제공...

작성 글자: 0원문 글자: 7,327작성 단락: 0/253