레디스 클러스터
1. 개요
1. 개요
레디스 클러스터는 레디스가 제공하는 분산 데이터베이스 기능으로, 고가용성과 수평 확장을 목표로 설계되었다. 단일 레디스 인스턴스의 메모리 및 처리량 한계를 극복하기 위해, 데이터를 여러 노드에 분산 저장하고 병렬로 처리할 수 있도록 한다.
이를 위해 데이터 샤딩 기법을 사용하며, 총 16384개의 해시 슬롯으로 데이터를 분할한다. 각 키는 CRC16 알고리즘을 통해 특정 해시 슬롯에 매핑되며, 각 슬롯은 클러스터 내의 마스터 노드에 할당된다. 이 아키텍처를 통해 최대 1000개의 마스터 노드까지 확장이 가능하다.
또한 고가용성을 위해 자동 페일오버 기능을 제공한다. 클러스터를 구성하는 모든 노드는 풀 메쉬 토폴로지로 연결되어 서로의 상태를 지속적으로 모니터링한다. 마스터 노드에 장애가 발생하면, 해당 마스터의 복제본 노드가 자동으로 새로운 마스터로 승격되어 서비스 중단을 최소화한다.
클라이언트 애플리케이션은 특별한 프록시 서버 없이도 레디스 클라이언트 라이브러리를 통해 클러스터와 통신할 수 있다. 클라이언트는 초기 연결 시 클러스터의 해시 슬롯 배치 정보를 획득하고 캐싱하여, 이후 요청을 적절한 노드로 직접 라우팅하는 방식으로 동작한다.
2. 데이터 샤딩과 해시 슬롯
2. 데이터 샤딩과 해시 슬롯
레디스 클러스터는 데이터를 여러 노드에 분산 저장하여 성능과 확장성을 높이는 데이터 샤딩을 핵심 기능으로 한다. 이를 위해 해시 슬롯이라는 개념을 사용하며, 총 16384개의 고정된 슬롯이 존재한다. 클러스터에 저장되는 모든 키는 CRC16 알고리즘을 통해 하나의 해시 슬롯에 매핑된다. 이 매핑 공식은 CRC16(key) mod 16384이다.
클러스터를 구성하는 각 마스터 노드는 전체 해시 슬롯 중 일부 범위를 할당받아 관리한다. 예를 들어, 3개의 마스터 노드로 구성된 클러스터에서는 슬롯이 대략 균등하게 나누어져 각 노드가 약 5460개의 슬롯을 담당하게 된다. 클라이언트가 특정 키에 대한 명령을 실행하면, 해당 키의 해시 슬롯을 계산하고 그 슬롯을 관리하는 마스터 노드로 연결이 리디렉션된다.
이러한 구조는 클러스터의 확장성을 높인다. 새로운 마스터 노드를 추가하거나 기존 노드를 제거할 때는 리샤딩 과정을 통해 해시 슬롯의 소유권을 다른 노드들 사이에서 재분배하면 된다. 슬롯은 노드 간에 자유롭게 이동할 수 있으며, 이동 중에도 해당 슬롯의 데이터는 정상적으로 접근 가능하다. 또한, 해시태그 기능을 사용하면 서로 다른 키를 동일한 해시 슬롯에 강제로 매핑할 수 있어, MGET과 같은 다중 키 명령을 클러스터 환경에서도 사용할 수 있게 해준다.
3. 고가용성과 페일오버
3. 고가용성과 페일오버
레디스 클러스터는 고가용성을 핵심 목표로 설계되어, 시스템의 지속적인 운영을 보장한다. 이를 위해 각 마스터 노드에는 하나 이상의 복제본 노드가 구성되며, 모든 노드는 풀 메쉬 토폴로지로 연결되어 서로의 상태를 지속적으로 모니터링한다. 노드 간 통신은 클라이언트 포트와 별도의 클러스터 버스 포트를 통해 이루어지며, PING과 PONG 패킷을 교환하여 장애를 감지한다.
주요 고가용성 메커니즘은 자동 페일오버다. 마스터 노드에 장애가 발생하면, 다른 노드들이 이를 감지하고 투표를 통해 해당 마스터의 복제본 노드 중 하나를 새로운 마스터로 승격시킨다. 이 과정은 사용자의 개입 없이 자동으로 수행되어 서비스 중단 시간을 최소화한다. 또한, 자동 복제본 마이그레이션 기능을 통해 클러스터는 각 마스터가 최소 하나의 복제본을 보유하도록 자동으로 재조정하여 시스템의 전반적인 안정성을 높인다.
페일오버 후, 원래의 마스터 노드가 복구되어 재시작되면, 이 노드는 자동으로 새로운 마스터의 복제본 노드로 전환되어 클러스터에 다시 합류한다. 이러한 설계는 단일 장애 지점을 제거하고, 하드웨어 또는 네트워크 문제 발생 시에도 데이터 접근성을 유지하도록 한다.
4. 클러스터 구성 및 노드
4. 클러스터 구성 및 노드
레디스 클러스터는 최소 3개의 마스터 노드로 구성되며, 실제 운영 환경에서는 각 마스터에 하나 이상의 복제본 노드를 추가해 고가용성을 확보하는 것이 일반적이다. 예를 들어, 3개의 마스터와 각각의 복제본을 포함해 총 6개의 노드로 구성하는 것이 일반적인 구성이다. 각 노드는 고유한 노드 ID를 가지며, 이 ID는 클러스터 내에서 노드를 식별하는 데 사용된다.
클러스터 내 모든 노드는 풀 메쉬 토폴로지로 연결되어 서로의 상태를 지속적으로 모니터링한다. 이를 위해 각 노드는 클라이언트 통신용 포트와 별도로 클러스터 버스 포트를 연다. 일반적으로 클라이언트 포트 번호에 10000을 더한 포트를 사용한다. 노드 간에는 PING과 PONG 패킷을 교환하여 하트비트를 유지하고, 장애를 감지한다.
클러스터의 구성 정보는 각 노드의 메모리에 유지되며, cluster-config-file에 지정된 파일(기본값 nodes.conf)에도 지속적으로 저장된다. 이 파일에는 노드 ID, 역할, 할당된 해시 슬롯 범위, 마스터-복제본 관계 등 클러스터의 전체 상태가 기록되어, 노드 재시작 시 구성을 복원하는 데 사용된다.
5. 클라이언트와의 통신
5. 클라이언트와의 통신
레디스 클러스터에서 클라이언트는 일반적인 단일 인스턴스에 접속하는 방식과는 다른 방식으로 통신한다. 클라이언트는 초기 연결 시 클러스터 내 임의의 노드에 접속하며, 해당 노드는 자신이 처리할 수 없는 키에 대한 요청을 받으면 클라이언트에게 올바른 노드로 리디렉션한다. 이때 MOVED 또는 ASK 리디렉션 응답이 사용된다.
클라이언트는 MOVED 리디렉션을 받으면, 해당 키가 속한 해시 슬롯과 그 슬롯을 담당하는 마스터 노드의 정보를 얻는다. 대부분의 레디스 클라이언트 라이브러리(Jedis, Lettuce, Redisson 등)는 이 정보를 내부에 캐싱하여 이후 동일한 키에 대한 요청은 캐싱된 노드로 직접 전송한다. 이를 통해 매번 리디렉션되는 오버헤드를 줄이고 성능을 향상시킨다. ASK 리디렉션은 리샤딩 작업이 진행 중일 때 일시적으로 발생하며, 클라이언트는 해당 요청만 임시로 지정된 노드로 보내고 슬롯 매핑 캐시는 업데이트하지 않는다.
클러스터를 지원하는 클라이언트는 또한 클러스터의 전체 토폴로지(노드 목록과 슬롯 매핑)를 주기적으로 갱신해야 한다. 페일오버나 노드 추가/삭제로 인해 클러스터 구성이 변경되면, 클라이언트는 MOVED 응답을 받거나 주기적인 갱신을 통해 새로운 구성을 파악하고 연결을 조정한다. redis-cli 도구를 사용할 때는 -c 옵션을 주면 이 리디렉션 로직을 자동으로 처리하는 클러스터 모드로 동작한다.
6. 설정 및 운영
6. 설정 및 운영
레디스 클러스터를 설정하고 운영하기 위해서는 몇 가지 필수 구성 단계와 운영 중 고려해야 할 명령어 및 절차가 있다.
클러스터를 시작하려면 먼저 각 레디스 노드의 설정 파일에서 cluster-enabled 파라미터를 yes로 설정해야 한다. 이는 해당 인스턴스를 클러스터 모드로 전환한다. 또한 cluster-config-file을 통해 클러스터 구성 정보가 저장될 파일 경로를 지정할 수 있다. 클러스터를 초기 생성하는 가장 일반적인 방법은 redis-cli 유틸리티의 --cluster create 명령어를 사용하는 것이다. 예를 들어, 3개의 마스터 노드와 각각 1개의 복제본 노드를 가지는 총 6노드 클러스터를 구성하려면 해당 노드들의 IP 주소와 포트를 나열하고 --cluster-replicas 1 옵션을 추가하여 실행한다. 이 명령은 해시 슬롯을 마스터 노드들에 자동으로 분배하고 복제 관계를 설정한다.
운영 중에는 클러스터 상태를 확인하고 유지보수하는 작업이 필요하다. CLUSTER NODES 또는 redis-cli --cluster check 명령을 사용하면 현재 클러스터의 토폴로지, 노드 역할, 해시 슬롯 분배 상태 등을 상세히 확인할 수 있다. 클러스터를 확장하기 위해 새로운 마스터 노드를 추가할 때는 redis-cli --cluster add-node 명령을 사용하며, 이후 redis-cli --cluster reshard 명령을 실행하여 기존 마스터 노드들의 해시 슬롯 중 일부를 신규 노드로 이동시켜 데이터를 재분배해야 한다. 반대로 노드를 제거할 때는 제거 대상 마스터 노드가 보유한 모든 해시 슬롯을 다른 노드로 먼저 이동시킨 후 redis-cli --cluster del-node 명령으로 클러스터에서 제외한다.
장애 복구 측면에서 레디스 클러스터는 자동 페일오버를 지원한다. 마스터 노드에 장애가 발생하면 해당 복제본 노드가 새로운 마스터로 승격된다. 운영자는 수동으로 특정 복제본 노드에서 CLUSTER FAILOVER 명령을 실행하여 계획된 페일오버를 유도할 수도 있다. 클러스터의 안정성을 위해 cluster-node-timeout 파라미터를 적절히 설정하는 것이 중요하며, 이 값은 노드 장애 판단의 기준이 된다. 또한 cluster-require-full-coverage 파라미터를 no로 설정하면 일부 노드가 다운되어도 사용 가능한 해시 슬롯에 대한 서비스는 중단되지 않도록 할 수 있어 가용성을 높일 수 있다.
7. 장단점
7. 장단점
레디스 클러스터는 수평 확장과 고가용성을 동시에 달성할 수 있는 강력한 솔루션이지만, 특정 제약 사항과 운영 복잡성을 동반한다.
장점으로는 먼저 데이터 샤딩을 통한 선형적 수평 확장이 가능하다는 점이다. 단일 레디스 인스턴스의 메모리와 처리량 한계를 극복하기 위해 최대 1000개의 마스터 노드까지 확장할 수 있다. 둘째, 자동 페일오버와 복제본을 통한 고가용성을 제공한다. 마스터 노드에 장애가 발생하면 복제본 노드가 자동으로 승격되어 서비스 중단을 최소화한다. 셋째, 클라이언트 측 리다이렉션과 슬롯 정보 캐싱을 통해 분산 데이터베이스에 대한 접근이 비교적 투명하게 이루어진다. 마지막으로, 풀 메쉬 토폴로지와 가십 프로토콜을 사용하여 노드 간 상태 정보를 효율적으로 공유하며, 관리 포인트를 중앙 프록시 서버가 아닌 레디스 자체에 둠으로써 아키텍처를 단순화한다.
반면, 단점도 존재한다. 첫째, 트랜잭션이나 다중 키 연산(MGET, MSET 등)은 동일한 해시 슬롯에 속한 키에 대해서만 지원된다. 이를 위해 해시태그를 사용할 수 있지만, 데이터 분포의 불균형을 초래할 수 있다. 둘째, 클러스터 모드에서는 데이터베이스를 여러 개 사용할 수 없으며, 항상 데이터베이스 0만 사용된다. 셋째, 운영상의 복잡성이 증가한다. 리샤딩, 노드 추가/제거, 상태 모니터링 등이 단일 인스턴스 운영보다 까다로우며, cluster-require-full-coverage 설정에 따라 일부 슬롯을 사용할 수 없게 되면 전체 클러스터가 쓰기 불능 상태에 빠질 수 있다. 넷째, 풀 메쉬 연결로 인한 연결 수 증가와 하트비트 트래픽이 발생하지만, 이는 설계상 큰 부하로 이어지지 않도록 최적화되어 있다.
