레디스를 사용하다보면 다음과 같은 용어들이 자주 등장하게 된다.
- Sharding
- Cluster
- Replica
- Sentinel
도대체 위 개념들은 레디스 클러스터에 어떻게 적용되고, 어떤 용도로 사용되는 것일까? 최근에 Redis Cluster 아키텍처 구성을 고민하다 보니 개념에 대한 이해가 충분치 않다는 것을 느꼈고, 글로 정리하여 추후에 활용할 수 있도록 한다.
개념 정리
1. Redis Cluster vs Sentinel
센티넬은 Master 노드가 죽었을 때 동일한 데이터를 복제하고 있던 Replica가 quorum에 의해 자동으로 Master로 승격되는 failover 기능을 제공하는 아키텍처 패턴이다.
센티넬 방식을 사용할 경우 Redis Sharding 기능을 사용할 수 없다.
즉, Master/Replica 구조 내에서 failover를 통해 장애 복구가 가능하다 정도로 이해하면 되겠다.
반면, 레디스 클러스터는 Sharding과 Replica를 활용한 failover 모두를 사용 가능하다.
2. Sharding
그럼 도대체 Sharding이 뭘까?
우리가 개발을 하다보면 데이터베이스를 Master-Replica 구조로 나누는 것을 자주 목격하게 된다. Master DB는 쓰기 작업을 담당하고, Latency가 존재하긴 하나 Master에 쓰여진 데이터는 곧바로 Replica로 Sync가 이루어지게 된다.
동기화가 이루어진 Replica는 Read 작업에 주로 사용되게 된다.
그럼, 데이터베이스의 사례에서 볼 수 있듯 동일한 데이터를 가진 Active-Active 성격의 아키텍처 패턴을 Sharding이라고 이해하면 되는가?
아니다. 위와 같은 구분은 엄밀한 의미에서 잘못되었다.
| Matser-Replica | Sharding |
| Matser Node의 데이터를 주기적으로 Replica에 Sync하는 작업을 의미한다. 이는 말 그대로 복제의 의미이며, Master가 가용 불가능 할 때 failover를 통해 Replica -> Master 승격이 가능한 구조이다. | 하나의 저장소를 수평 확장하는 개념으로 이해해야 한다. 가령 레디스의 경우 16,384개의 해시 슬롯을 관리하는데, 샤딩을 사용할 경우 Master 노드가 여러 개로 분산되게 된다. Master 1, Master 2, Master 3은 16,384 개의 해시 슬롯을 정해진 범위에 맞게 나누어 관리한다. 이를 통해 성능을 개선하고 데이터를 분산 관리할 수 있게 된다. |
즉 우리가 데이터베이스를 나누어 관리하는 것은 Master-Replica 구조, 다시 말해 복제의 개념에 보다 가깝다.
Redis는 마스터를 다중으로 나누어 관리하는 Sharding을 적용하면서도 동시에 각 Shard에 대한 Replica를 추가적으로 관리한다. 그래야만 특정 샤드에 문제가 생겼을 때 failover를 통한 복구가 가능하기 때문이다.
3. Redis Cluster
그럼 우리가 특정 서비스에 레디스를 도입할 때 Redis Cluster와 Sentinel 중 어떤 아키텍처를 선택해야 하는가?
수평 확장을 통한 데이터 분산 관리 및 성능 개선을 고려할 필요가 없는 소규모 아키텍처에서는 Sentinel을 사용해도 무방하다. 레디스 노드는 Master, Replica 구조로 관리하고 센티넬 노드를 활용하여 장애 상황에 대응하기 위한 failover 기능 정도만 적용하는 것이다.
반면 대규모 아키텍처에서는 반드시 Redis Cluster를 적용해야 한다. Master 노드를 Sharding을 적용하여 다수 개로 나누어 관리하고, 각각에 failover 상황을 대비하기 위해 replica를 배치하는 것이다.

이 경우 failover 과정에서 발생하는 노드 간의 합의인 quorum은 Master 노드 들이 수행하게 된다. 과반 수의 마스터가 동의하게 되면 장애라고 판단되는 Master 노드의 Replica를 마스터로 승격시키는 것이다.
유의 사항
프로덕션에서 Redis Cluster를 사용하는 것은 인프라적 관점에서 타당한 것처럼 보인다.
하지만 해시 슬롯을 나누어 관리하는 클러스터를 도입하게 되면 개발자, 다시 말해 애플리케이션 관점에서 신경 쓸 부분이 늘어나게 된다.
가령 다음의 상황을 가정해 보자.
동시성과 순차성을 고려하여 개발해야 하는 서비스가 있다.
기존에는 Database Lock을 통해 처리하고 있었으나, 성능 개선을 위해 Redis Client인 Redission을 도입하여 Redis 분산락으로 리팩토링을 진행하려고 한다.
특정 데이터 레코드에 대해 분산락을 적용하려면 반드시 원자성이 보장되어야만 한다. 만일 Sharding을 적용하지 않았다면 해당 레코드에 최초로 요청이 들어왔을 때 Redis에 Set을 하기 때문에 다른 스레드에서 해당 레코드를 조작할 수 없겠지만, 클러스터 모드는 다르다.
데이터를 삽입할 때 같은 unique key를 가진 데이터 레코드는 반드시 특정 샤드(특정 마스터 노드)로 배정되도록 처리해야만 한다. 만일 해시 슬롯을 정의하지 않은 채 그냥 Cluster에 삽입 작업을 할 경우 다음과 같은 문제가 발생하게 된다.
- 첫 번째 요청 -> Master 1 (1번 샤드)에 적재
- 두 번째 요청 -> Master 2 (2번 샤드)에 적재
- 세 번째 요청 -> Master 3 (3번 샤드)에 적재
다중 요청이 들어왔을 때 데이터의 동시성을 보장하기 위해 Lock을 사용하는 것인데, 위와 같이 요청 마다 클러스터 내의 다른 노드로 데이터가 삽입된다면 Lock의 의미가 사라지게 된다. 따라서 같은 키를 가진 데이터는 반드시 원자성을 보장하기 위해 같은 샤드 노드에 배치시켜야 하는 이슈가 생기게 된다.
'CS' 카테고리의 다른 글
| [AMQP] RabbitMQ와 DLX/DLQ (0) | 2025.03.24 |
|---|---|
| Blocking/Non-Blocking(블로킹/논블로킹), Sync/Async(동기/비동기), Concurrent/Parallel(동시/병렬) (5) | 2024.10.11 |