Redis 클러스터 이해: 클라이언트가 올바른 샤드에 어떻게 접근하는지
James Reed
Infrastructure Engineer · Leapcell

배경: Redis 클러스터가 필요한 이유
Sentinel 모드는 마스터-슬레이브 모델을 기반으로 하며 읽기-쓰기 분리를 가능하게 합니다. 또한 자동 장애 조치를 지원하여 시스템 가용성을 향상시킵니다. 그러나 각 노드가 동일한 데이터를 저장하기 때문에 메모리가 낭비되고 온라인 확장이 어렵습니다.
결과적으로 Redis 클러스터(샤딩된 클러스터를 구현하기 위한 솔루션)가 탄생했습니다. Redis 3.0에서 도입된 이 기능은 Redis에서 분산 스토리지를 가능하게 합니다. 데이터를 샤딩하므로 각 Redis 노드가 다른 콘텐츠를 저장하여 온라인 확장 문제를 해결합니다. 또한 다양한 Redis 인스턴스에 데이터를 분산하여 대용량 데이터를 저장할 수 있으며 복제 및 장애 조치 기능도 제공합니다.
예를 들어 단일 Redis 인스턴스가 15GB 이상의 데이터를 저장하면 응답 시간이 느려집니다. 이는 Redis의 RDB 영구 저장 메커니즘 때문입니다. Redis는 RDB 영구 저장을 수행하기 위해 자식 프로세스를 포크하고 포크 작업에 걸리는 시간은 Redis 데이터 크기에 정비례합니다.
이 시점에서 자연스럽게 다음과 같이 생각할 수 있습니다. 15GB의 데이터를 여러 노드에 분산하지 않는 이유는 무엇일까요? 이것이 바로 Redis 샤딩된 클러스터의 동기입니다. 그렇다면 샤딩된 클러스터는 정확히 무엇일까요? 예를 들어 살펴보겠습니다. Redis를 사용하여 15GB의 데이터를 저장하려면 단일 Redis 인스턴스를 사용하거나 3개의 Redis 인스턴스로 샤딩된 클러스터를 만들 수 있습니다. 다음은 비교입니다.
샤딩된 클러스터와 Redis 클러스터의 차이점: Redis 클러스터는 Redis 3.0에 도입된 공식 샤딩된 클러스터 구현입니다.
이제 데이터가 서로 다른 Redis 인스턴스에 분산되어 있으므로 클라이언트는 액세스하려는 데이터를 보유한 인스턴스를 어떻게 알 수 있을까요? Redis 클러스터가 이를 어떻게 처리하는지 살펴보겠습니다.
클라이언트가 액세스할 샤드를 어떻게 알 수 있을까요?
Redis 클러스터는 해시 슬롯을 사용하여 데이터와 인스턴스 간의 매핑을 관리합니다.
샤딩된 클러스터는 16,384개의 슬롯으로 나뉩니다. Redis에 들어가는 각 키-값 쌍은 키를 기준으로 해싱되어 이러한 16,384개의 슬롯 중 하나에 할당됩니다. 해싱 방법은 간단합니다. CRC16 알고리즘은 16비트 값을 계산한 다음 16,384로 나눕니다. 데이터베이스의 모든 키는 이러한 16,384개의 슬롯 중 하나에 속하며 클러스터의 모든 노드는 해당 슬롯의 일부를 처리합니다.
클러스터의 각 노드는 해시 슬롯의 일부를 담당합니다. 클러스터에 노드 A, B, C의 세 개가 있다고 가정합니다. 그러면 각 노드는 약 16,384/3개의 슬롯을 담당합니다. 가능한 분포는 다음과 같습니다.
- 노드 A는 해시 슬롯 0–5460을 처리합니다.
- 노드 B는 해시 슬롯 5461–10922를 처리합니다.
- 노드 C는 해시 슬롯 10923–16383을 처리합니다.
그렇다면 클라이언트가 해당 데이터를 보유하지 않은 Redis 인스턴스에 읽기/쓰기 작업을 보내면 어떻게 될까요? MOVED 및 ASK 리디렉션이 시작됩니다.
3. 대상 인스턴스에 데이터가 없는 경우 어떻게 될까요?
Redis 클러스터 모드에서 노드는 다음과 같이 요청을 처리합니다.
- 해시 슬롯 매핑을 사용하여 노드는 요청된 Redis 키가 현재 노드에 속하는지 확인합니다.
- 해시 슬롯이 이 노드에서 관리되지 않으면 MOVED 리디렉션을 반환합니다.
- 해시 슬롯이 실제로 이 노드에서 관리되고 슬롯에 키가 있으면 해당 결과를 반환합니다.
- Redis 키가 슬롯에 없으면 해시 슬롯이 현재 마이그레이션 중인지(MIGRATING) 확인합니다.
- Redis 키가 마이그레이션 중이면 ASK 오류를 반환하여 클라이언트를 키가 이동하는 대상 서버로 리디렉션합니다.
- 해시 슬롯이 마이그레이션되지 않으면 슬롯이 가져오기 중인지 확인합니다.
- 슬롯이 가져오기 중이고 ASKING 플래그가 있으면 작업이 직접 진행됩니다. 그렇지 않으면 MOVED 리디렉션이 반환됩니다.
3.1 MOVED 리디렉션
클라이언트가 Redis 인스턴스에 읽기/쓰기 작업을 보내고 계산된 슬롯이 해당 노드에 속하지 않으면 Redis는 MOVED 리디렉션 오류를 반환합니다. 이 응답에는 슬롯이 상주하는 올바른 Redis 노드의 IP와 포트가 포함됩니다. 이것이 Redis 클러스터에서 사용하는 MOVED 리디렉션 메커니즘입니다.
3.2 ASK 리디렉션
ASK 리디렉션은 일반적으로 클러스터 리샤딩 중에 발생합니다. 리샤딩으로 인해 슬롯이 마이그레이션됩니다. 클라이언트가 소스 노드에 액세스하려고 하면 데이터가 이미 대상 노드로 이동되었을 수 있습니다. ASK 리디렉션은 마이그레이션 프로세스 중에 클라이언트를 새 노드로 안내하여 이 시나리오를 처리하는 데 도움이 됩니다.
4. 노드는 서로 어떻게 통신할까요?
Redis 클러스터는 여러 노드로 구성됩니다. 이들은 어떻게 통신할까요? 가십 프로토콜을 통해 통신합니다. 가십은 각 노드가 노드 목록에서 _k_개의 노드를 주기적으로 선택하고 모든 노드가 합의에 도달할 때까지 자신이 보유한 정보를 전파하는 메시지 전파 프로토콜입니다. 이를 알고리즘 수렴이라고 합니다.
가십 프로토콜의 기본 아이디어: 노드는 네트워크의 다른 노드와 일부 정보를 공유하려고 합니다. 주기적으로 임의로 몇 개의 노드를 선택하여 정보를 보냅니다. 그러면 해당 노드는 동일한 작업을 수행하여 정보를 다른 임의로 선택된 노드로 전파합니다. 일반적으로 정보는 단 하나의 노드가 아닌 _N_개의 노드로 전파됩니다. 이 _N_을 _fanout_이라고 합니다.
Redis 클러스터는 가십 프로토콜을 사용하여 노드 간에 정보를 교환합니다. 여기에는 노드 장애, 새 노드 추가, 마스터-슬레이브 변경, 슬롯 할당 등에 대한 데이터가 포함됩니다. 가십 프로토콜에는 ping
, pong
, meet
및 fail
을 포함한 여러 유형의 메시지가 포함됩니다.
- meet 메시지: 새 노드가 가입하도록 알립니다. 발신자는 수신자에게 현재 클러스터에 가입하도록 알립니다.
meet
메시지가 성공적으로 수신되면 수신 노드는 클러스터에 가입하고 주기적인ping
및pong
교환을 시작합니다. - ping 메시지: 각 노드는 클러스터의 다른 노드에 매초
ping
메시지를 보냅니다. 이 메시지에는 주소, 슬롯, 상태, 마지막 통신 시간 등 두 개의 알려진 노드에 대한 정보가 포함됩니다. - pong 메시지: 성공적인 통신을 확인하기 위해
ping
또는meet
메시지에 대한 응답으로 전송됩니다. 또한 두 개의 알려진 노드에 대한 정보가 포함됩니다. - fail 메시지: 노드가 클러스터의 다른 노드가 오프라인 상태임을 확인하면 전체 클러스터에
fail
메시지를 브로드캐스트합니다. 이 메시지를 받으면 다른 노드는 해당 노드를 오프라인 상태로 표시합니다.
특히 각 노드는 클러스터 버스를 통해 다른 노드와 통신합니다. 이 통신은 일반 Redis 포트에서 10,000을 더한 특수 포트를 사용합니다. 예를 들어 노드의 서비스 포트가
6379
이면 클러스터 통신 포트는16379
입니다. 노드는 통신을 위해 특수 바이너리 프로토콜을 사용합니다.
5. 클러스터에서 노드가 실패하면 어떻게 될까요?
Redis 클러스터는 고가용성을 지원합니다. 클러스터의 노드가 실패하면 시스템은 장애 조치를 사용하여 클러스터가 계속해서 외부 서비스를 제대로 제공하도록 합니다.
노드 오프라인
Redis 클러스터는 장애 감지를 위해 ping
/pong
메시지를 사용합니다. 여기에는 주관적인 및 객관적인 오프라인 상태가 포함됩니다.
- 주관적인 오프라인(pfail): 한 노드가 다른 노드에 연결할 수 없다고 생각하고 오프라인으로 표시합니다. 그러나 이는 결정적인 실패 판단이 아닙니다. 이는 한 노드의 관점만 반영하며 정확하지 않을 수 있습니다.
- 객관적인 오프라인(fail): 클러스터의 _여러 노드_가 연결할 수 없다는 데 동의하면 노드를 실제로 오프라인 상태로 표시합니다. 이는 합의에 기반한 결정입니다. 오프라인 노드가 해시 슬롯을 소유한 마스터인 경우 장애 조치 프로세스가 트리거되어 이를 대체합니다.
예를 들어 노드 A가 노드 B를 주관적으로 오프라인 상태로 표시하면 노드 B의 상태 정보를 다른 노드로 보냅니다. 노드 C가 이 메시지를 수신하고 구문 분석하여 노드 B가
pfail
로 표시된 것을 확인하면 객관적인 오프라인 프로세스를 트리거합니다.
- 오프라인 노드가 마스터인 경우 Redis 클러스터는 슬롯을 소유한 모든 마스터 간에 투표 프로세스를 시작합니다. 절반 이상이 오프라인 상태로 보고하면 공식적으로 객관적인 오프라인 상태로 표시됩니다.
장애 조치 복구
오류가 감지되면 오프라인 노드가 마스터인 경우 고가용성을 유지하기 위해 복제본(슬레이브)을 선택하여 대체해야 합니다. 장애 조치 프로세스에는 다음 단계가 포함됩니다.
- 자격 확인: 복제본이 실패한 마스터를 대체할 조건을 충족하는지 확인합니다.
- 장애 조치 지연 준비: 복제본이 자격이 있으면 장애 조치를 시작하기 전에 지연 시간을 설정합니다.
- 선거 시작: 장애 조치 지연 시간이 만료되면 복제본이 선거 프로세스를 시작합니다.
- 투표 수집: 해시 슬롯을 보유한 마스터만 투표할 수 있습니다. 후보 복제본은 마스터를 대체하기 위해 진행하려면 충분한 투표(절반 이상)를 수집해야 합니다.
백엔드 프로젝트 호스팅을 위한 최고의 선택, Leapcell입니다.
Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.
다국어 지원
- Node.js, Python, Go 또는 Rust로 개발하십시오.
무제한 프로젝트를 무료로 배포
- 사용량에 대해서만 비용을 지불하고 요청이나 요금은 없습니다.
최고의 비용 효율성
- 유휴 요금 없이 사용한 만큼 지불합니다.
- 예: $25는 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
간소화된 개발자 경험
- 간편한 설정을 위한 직관적인 UI
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합
- 실행 가능한 통찰력을 위한 실시간 메트릭 및 로깅
손쉬운 확장성 및 고성능
- 고도의 동시성을 쉽게 처리할 수 있도록 자동 확장이 가능합니다.
- 운영 오버헤드가 없으므로 구축에만 집중하십시오.
설명서에서 자세히 알아보세요!
X에서 팔로우하세요: @LeapcellHQ