오늘은 Redis에 대해 정리하려고 합니다. Redis는 무엇일까요?
Redis("Re mote DI ctionary S ervice")
Redis에 대한 가장 정확한 설명은 데이터 구조 서버라는 것이에요.🤓 Redis의 이러한 특정 특성으로 인해 개발자들 사이에서 인기가 높아지고 채택이 이루어졌습니다. 데이터를 정렬하고, 저장하고, 다루는 방식이 정말 직관적이고 간편하거든요. 특히 Redis는 단순한 캐시 역할을 넘어서, 본격적인 데이터베이스로도 활용될 수 있어요.
기본적으로 Redis는 MySQL이나 PostgreSQL과 같은 다른 "실제" 데이터베이스 앞에 캐시로 사용되는 메모리 내 데이터베이스로, 애플리케이션 성능을 개선하는 데 도움이 됩니다. 메모리 속도를 활용하고 중앙 애플리케이션 데이터베이스의 부하를 덜어주죠.
하지만 많은 사용 사례에서 Redis는 본격적인 기본 데이터베이스로 사용할 수 있다는 충분한 보장을 제공합니다. Redis 플러그인과 다양한 고가용성(HA) 설정과 결합된 데이터베이스로서의 Redis는 특정 시나리오와 워크로드에 매우 유용해졌습니다.
또 다른 중요한 측면은 Redis가 캐시와 데이터 저장소의 경계를 모호하게 만들었다는 것이에요. 여기서 이해해야 할 중요한 사항은 메모리에서 데이터를 읽고 조작하는 것이 SSD나 HDD를 사용하는 기존 데이터 저장소에서 가능한 모든 것보다 훨씬 빠르다는 것입니다.
단일 Redis 인스턴스
단일 Redis 인스턴스는 Redis의 가장 간단한 배포예요. 이를 통해 사용자는 서비스를 성장시키고 속도를 높이는 데 도움이 되는 작은 인스턴스를 설정하고 실행할 수 있습니다. 그러나 이 배포에는 단점이 없는 것은 아니에요. 예를 들어, 이 인스턴스가 실패하거나 사용할 수 없는 경우 Redis에 대한 모든 클라이언트 호출이 실패하여 시스템의 전반적인 성능과 속도가 저하돼요. 😂 그래서 Redis를 제대로 사용하려면 고가용성(HA)을 고려해야 해요.
고가용성(HA)과 Redis 복제
Redis에서 고가용성을 구현하는 데 가장 널리 쓰이는 방법 중 하나는 "복제"입니다. 기본적으로 Redis는 단일 인스턴스에서 시작하지만, 단일 인스턴스는 안정성 측면에서 취약합니다. 예를 들어, 단일 인스턴스가 다운되거나 네트워크 연결 문제가 발생하면, 해당 인스턴스를 사용하는 모든 클라이언트 요청이 실패하게 되죠. 이런 상황에서는 애플리케이션 전체의 성능과 신뢰성에 심각한 문제가 생길 수 있어요 🥲
이를 해결하기 위해 복제를 통해 고가용성을 구현해야 해요. 기본적으로 복제란 하나의 기본(primary) 인스턴스가 데이터를 관리하고, 동일한 데이터를 여러 보조(replica) 인스턴스에 복사하는 과정을 의미하죠. 이렇게 하면 몇 가지 주요 이점을 얻을 수 있어요. 첫 번째는 읽기 확장성(Read Scalability), 장애 조치(Failover)입니다.
보조 인스턴스가 읽기 요청을 처리할 수 있기 때문에, 읽기 부하가 분산되고, 인스턴스가 다운되더라고 보조 인스턴스를 기본으로 승격시켜 서비스 중단을 최소화할 수가 있죠.
복제 과정의 핵심: 복제 ID와 오프셋
Redis 복제의 동작 원리를 이해하려면 복제 ID(replication ID)와 오프셋(offset)의 개념을 알아야 해요. 🧑💻
- 복제 ID(replication ID): Redis의 기본(primary) 인스턴스는 복제를 관리하기 위해 고유한 ID를 생성해요. 이 ID는 복제본(replica) 인스턴스가 어느 기본(primary) 인스턴스의 데이터를 복제하고 있는지를 식별하는 데 사용됩니다.
- 오프셋: 오프셋은 Redis의 기본 인스턴스에서 발생한 모든 작업을 추적하는 번호예요. 복제본은 자신이 마지막으로 동기화된 작업의 오프셋을 기록합니다.
Replication ID, offset
복제본이 기본 인스턴스에서 동기화를 유지하려면, 두 가지 상황이 발생할 수 있어요.
- 부분 동기화: 기본 인스턴스와 복제본 간의 오프셋 차이가 작으면, 필요한 명령만 복제본으로 전송해 동기화합니다.
- 전체 동기화: 기본 인스턴스와 복제본의 복제 ID가 다르거나, 오프셋 차이가 크다면, 전체 데이터를 다시 동기화합니다. 이 과정에서는 기본 인스턴스가 RDB 스냅샷을 생성해 전송하며, 추가적인 명령은 버퍼링 되어 동기화가 완료된 뒤 전송됩니다.
이 과정은 효율적이지만, 복잡한 설정이 필요한 경우도 있습니다. 예를 들어, 여러 복제본이 있는 환경에서 기본 인스턴스가 새롭게 설정되면, Redis는 이전 복제본과의 데이터를 동기화하기 위해 다양한 동작을 수행해야 합니다. 이 모든 과정이 잘 조율되면 데이터 일관성과 가용성을 모두 유지할 수 있죠.
Redis Sentinel
Redis의 고가용성을 더욱 강화하기 위해 Sentinel이라는 특별한 시스템이 사용돼요. 이 시스템은 Redis의 기본(primary) 인스턴스와 보조(replica) 인스턴스가 제대로 작동하는지를 계속해서 확인해요. 마치 끊임없이 감시하는 안전망 같은 존재라고 할 수 있죠.
덕분에 애플리케이션이 언제든지 Redis와 안정적으로 연결될 수 있다는 신뢰감을 제공해요. 예를 들어, Redis에 어떤 문제가 생긴다면, Sentinel은 즉각적으로 이를 감지하고 시스템 관리자에게 알림을 보냅니다. 마치 "여기 문제가 생겼어요! 빨리 해결해 주세요!"라고 경고를 주는 거와 같아요. ✋
하지만 Sentinel이 단순히 문제를 알리는 역할만 하는 건 아닙니다. 만약 기본 인스턴스가 다운된다면, Sentinel은 충분한 수의 노드가 동의하는 경우(이를 쿼럼이라고 해요.), 보조 인스턴스를 새로운 기본으로 승격시키는 과정을 자동으로 처리합니다. 이를 통해 데이터 손실 없이 서비스가 중단되지 않고 계속 이어질 수 있습니다. 서비스 운영 중에 문제가 발생하더라도 빠르게 복구가 가능하다는 점에서 정말 믿음직스럽죠.
또 Sentinel은 Redis 클라이언트와도 밀접하게 협력해죠. 클라이언트가 Redis에 데이터를 쓰거나 읽어야 할 때, Sentinel은 현재 어떤 인스턴스가 기본 역할을 하고 있는지 알려줘요. 쉽게 말해, "지금은 이쪽으로 연결해야 해요"라고 친절히 안내해 주는 역할을 하는 셈입니다. Sentinel이 없다면 이러한 역할을 직접 설정하고 관리해야 할 텐데, Sentinel 덕분에 고가용성을 더욱 간단하게 누릴 수 있게 됩니다. 😆
Redis Cluster
Redis 클러스터는 대규모 데이터 처리를 위해 설계된 Reids의 분산 데이터 저장 방식이에요. 클러스터는 데이터를 여러 노드에 분산시켜 저장하며, 이를 통해 대량의 데이터와 트래픽을 처리할 수 있는 확장성과 안정성을 제공해요. 쉽게 말해, 하나의 서버에서 감당하기 어려운 데이터와 작업을 여러 서버가 나눠 처리하는 방식이에요. 클러스터를 사용하면 데이터가 특정 노드에 집중되는 문제를 해결하고, 동시에 데이터 복제와 장애 복구도 가능해지죠. 이를 통해 성능은 향상되고, 서비스의 안정성은 더 높아져요.
Redis 클러스터의 핵심은 슬롯(slot) 개념이에요. 클러스터는 총 16,384개의 해시 슬롯으로 나뉘어 있는데, 각 키는 특정 해시 슬롯에 매핑됩니다. 이 슬롯들은 클러스터 내의 노드들에 균등하게 분배되는데, 예를 들어 3개의 노드가 있다면 각 노드는 약 5,461개의 슬롯을 담당하게 됩니다. 클라이언트가 어떤 데이터를 요청하면, Redis는 해당 키가 매핑된 슬롯을 기반으로 적절한 노드에 요청을 보냅니다.
이렇게 키와 슬롯을 기반으로 데이터 분배를 자동으로 처리하니, 클라이언트를 직접 조정할 필요가 없이 정말 편리하죠. 🙂
이뿐만 아니라 Redis 클러스터는 복제(replication) 메커니즘도 포함하고 있어요. 각 노드에는 하나 이상의 보조(replica) 노트닥 연결되며, 이를 통해 데이터의 복제본이 유지됩니다. 예를 들어, 하나의 노드가 실패해도 해당 노드의 보조가 활성화되며 데이터 접근을 보장할 수 있어요. 이렇게 데이터가 복제되기 때문에 단일 장애 지점이 제거되고, 안정성이 더욱 높아집니다.