Redis 클러스터 스펙
Redis 클러스터 스펙 (Redis Cluster specification)
Redis Cluster는 수천 개 데이터 포인트를 여러 노드에 분산 저장하며, 대부분의 복제 같은 고가용성 기능과 가용성·일관성 보장을 유지하면서 자동 샤딩(샤딩/리샤딩) 을 제공하는 Redis의 분산 구현입니다. 이 문서는 Redis Cluster의 설계 목표와 핵심 구성 요소를 개념 수준에서 정리합니다.
출처: https://redis.io/docs/latest/operate/oss_and_stack/reference/cluster-spec/
설계의 주요 속성과 근거
- 목표: Redis Cluster의 목표는 1000개 노드까지 확장할 수 있는 선형 확장성(scalability), 샤딩 하에서도 최소한의 안전성 보장(write safety), 그리고 1~2개 노드 실패 시 계속 동작하는 가용성(availability)입니다.
- 구현된 부분집합: Redis Cluster는 단일 키 연산은 완전히 지원하지만, 다중 키 연산(multi-key operations)이나 다중 키 트랜잭션·Lua 스크립트는 모든 키가 같은 hash slot 안에 있을 때만 지원합니다.
- 쓰기 안전성(write safety): Redis Cluster는 쓰기 안전성을 위해 일관된 해시 슬롯 배치와 노드 간 합의(epoch) 메커니즘을 쓰며, 네트워크 분할 시에도 일관성을 보존하려 합니다.
- 가용성(availability): 마스터 노드에 장애가 나면 복제본(replica)이 승격되어 서비스를 이어갑니다. 노드 절반 이상이 마스터와 통신할 수 없으면 클러스터는 쓰기를 거부(리다이렉트 실패) 합니다.
- 성능(performance): 클러스터 노드 간 통신은 프록시 없이 직접 이뤄지며, 효과적으로 단일 Redis와 같은 성능을 유지합니다.
- 병합 연산 회피: 네트워크 분할 시 데이터 병합 충돌을 피하기 위해 Redis Cluster는 분할 후 재결합 시 최신 configuration epoch가 우선하는 "마지막이 이긴다" 방식을 씁니다.
클라이언트와 서버의 역할
Redis Cluster 프로토콜에서 클라이언트는 단순히 명령을 보내고, 서버는 명령 실행 외에 해시 슬롯 소유권·장애 감지·복제본 승격 등을 관리합니다. 클라이언트는 MOVED·ASK 리다이렉트에 응답해 올바른 노드로 요청을 다시 보냅니다.
주요 구성 요소 개요
키 분산 모델 (Hash slots)
Redis Cluster는 16384개의 해시 슬롯(hash slot) 을 사용합니다. 클러스터는 데이터를 16384개 슬롯으로 나누고, 각 노드가 전체 슬롯의 하위집합을 담당합니다. 키는 다음과 같은 방식으로 슬롯에 매핑됩니다.
HASH_SLOT = CRC16(key) mod 16384
슬롯 수와 해시 함수는 확장·축소 시 부분 재배치만 일어나도록 설계됐습니다. 키 공간이 커지면 노드를 추가해 슬롯 일부를 옮기고, 작아지면 슬롯을 합칩니다.
해시 태그 (Hash tags)
다중 키 연산을 가능하게 하려면 여러 키가 같은 슬롯에 놓이게 해야 합니다. 해시 태그는 키의 {...} 안 부분만 해시에 사용해, 같은 태그를 가진 키들을 같은 슬롯에 두는 규칙입니다. 예: this{foo}key와 another{foo}key는 foo로 해시되어 같은 슬롯에 배치됩니다. 이래야 그 키들에 대한 다중 키 연산·Lua 스크립트가 허용됩니다.
해시 태그의 제약: 서로 다른 키에 같은 태그를 쓰면 데이터가 한 슬롯에 몰려 핫스팟이 될 수 있으며, 실수로 일부 키를 강제로 같은 노드에 두는 것은 분산 균형을 해칠 수 있습니다.
클러스터 버스 (Cluster bus)
노드들은 TCP 클러스터 버스로 연결되며, 이 연결은 하트비트·gossip 메시지, 장애 시간 추정·최신 configuration epoch 알림, 리샤딩 데이터 이동 최적화 등을 전달합니다.
클러스터 토폴로지
전체 클러스터는 완전 그리드(fully connected) 형태로, 각 노드는 다른 모든 노드와 클러스터 버스 연결을 유지합니다. N개 노드일 때 각 노드는 N-1개 연결을 갖습니다.
노드 핸드셰이크
노드는 CLUSTER MEET ip port 명령으로 다른 노드에 소개되며, 이후 클러스터 버스 메시지 교환으로 서로를 알게 됩니다. gossip으로 네트워크 전체에 노드 정보가 퍼집니다.
리다이렉션과 리샤딩
- MOVED 리다이렉션: 클라이언트가 키를 담당하지 않는 노드에 명령을 보내면, 서버는
MOVED <slot> <ip>:<port>를 반환하고 클라이언트는 올바른 노드로 요청을 재전송합니다. 올바른 클라이언트는 이 리다이렉션을 캐시해 이후엔 바로 올바른 노드로 갑니다. - 라이브 재구성(live reconfiguration): 슬롯이 이전 중(migrating)이면 부분 이전 상태가 됩니다.
- ASK 리다이렉션: 슬롯이 대상 노드로 이전 중일 때 클라이언트는
ASK를 받아 그 슬롯의 일부 키만 임시로 대상 노드로ASKING지시 후 보냅니다. - 클라이언트 연결·리다이렉션 처리: 클라이언트는 편향되지 않게 노드에 요청을 분산하고, 리다이렉션 오류를 처리해야 합니다.
- 다중 키 연산: 같은 슬롯의 키에 대해서만 허용됩니다.
- 복제본으로 읽기 확장: 읽기 전용 요청을 복제본 노드가 서비스하도록 복제본 읽기(
READONLY)로 읽기를 확장할 수 있습니다.
장애 허용 (Fault tolerance)
- 하트비트·gossip 메시지: 각 노드는 다른 노드로 주기적으로 하트비트를, 무작위 노드로 gossip 메시지를 보내 서로의 상태를 결국 알게 합니다(
PING/PONG). - 하트비트 패킷 내용: 노드 ID, configuration epoch, 담당 슬롯, 마스터/복제 상태, 장애 시간 배열 등이 담깁니다.
- 장애 감지(failure detection): PFAIL(가능 장애) 플래그가 여러 노드에서 보고되면 FAIL로 승격되고, FAIL 상태가 클러스터에 전파됩니다.
구성 epoch와 복제본 승격
- 클러스터 current epoch: 노드 간 구성 버전 지표로, 각 노드는 자신의 current epoch를 유지하며 더 큰 epoch 메시지를 받으면 갱신합니다.
- configuration epoch: 각 마스터가 담당 슬롯 구성에 부여하는 증가 버전으로, 슬롯 소유권 충돌 시 더 큰 epoch가 이깁니다. 이로써 분할 후 재결합 때 낡은 구성을 가진 노드가 새 구성을 덮어쓰지 않게 합니다.
- 복제본 선거·승격: 마스터가 FAIL로 판정되면 복제본들이 선거를 치러 스스로를 새 마스터로 승격합니다. 승격된 복제본은 configuration epoch를 증가시키고 클러스터에 알립니다.
- replica rank: 선거 대기 시 복제본이 승급에 필요한 우선순위 지표.
- 마스터의 복제본 투표 응답: 마스터는 주어진 epoch에 대해 한 번만 복제본 선거 투표에 응답합니다.
- hash slots 구성 전파: 슬롯 소유권(구성) 변경은 gossip 메시지·
UPDATE·특정 명령으로 클러스터 전체에 전파됩니다. - 노드 재합류: 일시적으로 떨어진 노드는 gossip·하트비트로 최신 상태를 다시 배우고 클러스터에 재합류합니다.
- 복제본 마이그레이션: 덜 복잡한 복제본 상황을 개선하려고 마스터의 복제본을 다른 마스터로 재배치하는 방식입니다.
더 알아보기 (Learn more)
- Redis Cluster 운영 가이드: Scaling with Redis Cluster
- 슬롯·리다이렉트 관련 명령: CLUSTER, CLUSTER MEET, CLUSTER SLOTS
- RESP 프로토콜(노드 간 버스는 별도): RESP specification