Redis cluster, no longer vaporware.

Salvatore Sanfilippo

Redis 클러스터, 더 이상 베이퍼웨어가 아니다.

제 git 기록에서 Redis Cluster에 관한 첫 커밋은 2011년 3월 29일로 날짜가 찍혀 있는데, 그것은 "copy and commit" 병합이었습니다. 클러스터 브랜치의 기록은 작업 중인 커밋으로 완전히 엉망이어서 파괴되었으며, API와 시스템의 나머지 부분과의 상호작용에 대한 초기 아이디어를 구체화하기 위해서였습니다.

기본적으로 이 프로젝트는 약 4년 된 프로젝트입니다. 이는 Redis 프로젝트 전체 역사의 약 3분의 2에 해당합니다. 그런데도 오늘에야 비로소 저는 Redis 3.0.0의 첫 번째 릴리스 후보를 내놓습니다. 이 버전은 Cluster 지원이 포함된 첫 번째 버전입니다.

우여곡절

왜 이렇게 오래 걸렸는지 이해하는 것은 간단합니다. 자동 확장 방법이 없으면 Redis가 완전히 쓸모없어질 것처럼 보이던 때, 저는 클러스터 프로젝트를 상당히 서둘러 시작했습니다. 그러나 클러스터 프로젝트를 시작하기에 적절한 시점은 아니었습니다. Redis 자체가 너무 미성숙해서 아직 단일 인스턴스에 대한 확실한 이야기가 없었기 때문입니다.

잘못된 시기에 프로젝트를 시작한 실수를 저지르긴 했지만, 적어도 커뮤니티의 요청을 무시하는 함정에 빠지지는 않았습니다. 그래서 프로젝트는 다른 핵심 기능에 더 많은 여력을 제공하기 위해 무수히 여러 번 중단되었습니다. 지속성, 복제, 지연 시간, 내부 관찰은 클러스터보다 훨씬 더 많은 관심을 받았습니다. 사용자 층에 더 중요했기 때문입니다.

프로젝트의 또 다른 한계는 제가 시작할 당시 분산 프로그래밍에 대해 전혀 몰랐다는 점입니다. 저는 끔찍한 첫 설계를 만들었고, '제품' 요구 사항인 낮은 대기 시간, 선형 확장성, 작은 클러스터에서의 작은 오버헤드만 잘 포착했습니다. 그러나 모든 세부 사항은 잘못되었고, 필요한 것보다 훨씬 복잡했으며, 사용된 알고리즘도 안전하지 않았습니다.

작은 진전을 이루는 동안 저는 분산 프로그래밍의 기초를 공부하기 시작했고, Redis Cluster를 재설계했으며, 같은 아이디어를 새로운 버전의 Sentinel에 적용했습니다. 두 시스템에서 사용되는 분산 프로그래밍 알고리즘은 여전히 원시적입니다. 이 시스템들은 비동기 복제되는 최종 일관성 시스템이므로, 합의(consensus)나 그 외 사소하지 않은 문제를 다룰 필요가 없었습니다. 그러나 적어도 CP 저장소를 작성하는 것과 비교하면 단순한 문제를 다룰 때조차, 무엇을 하고 있는지 이해하지 못하면 결과 시스템이 완전히 잘못될 수 있습니다.

이 모든 문제에도 불구하고 저는 프로젝트를 계속 진행하며 구현을 수정하고 성숙도로 이끌기 위해 노력했습니다. 왜냐하면 작은 방 안의 코끼리처럼 Redis 커뮤니티 전체에 퍼져 있는 단순한 사실이 있었기 때문입니다. 사람들은 자신들의 노력으로 두 가지를 반복해서, 그리고 여러 번 완전히 망가진 방식으로 수행하고 있었습니다:

  1. 데이터셋을 N개의 노드에 샤딩하기.
  2. 특정 장애를 극복하기 위한 신속한 페일오버 절차.

문제 '2'는 너무 심각해서 어느 시점에 저는 Cluster가 완성되기 전에 Redis Sentinel 프로젝트를 시작하기로 결정했습니다. HA(고가용성) 시스템을 가능한 한 빨리 제공하고, '1'이 아니라 '2'만 필요한 대부분의 사용 사례에 Redis Cluster보다 더 적합한 시스템을 제공하기 위해서였습니다.

마침내 저는 이러한 노력의 첫 번째 실질적인 결과를 보기 시작했고, 이제 우리는 릴리스 후보를 확보했습니다. 이는 채택을 얻고, 남은 버그를 수정하며, 시스템을 더 점진적으로 개선하는 데 필요한 기본적인 이정표입니다.

실제로 무엇을 하는가?

Redis Cluster는 기본적으로 데이터 샤딩 전략입니다. 클러스터가 실행되는 동안 키를 한 노드에서 다른 노드로 재샤딩할 수 있으며, 특정 종류의 장애에서 시스템이 살아남을 수 있도록 하는 페일오버 절차도 함께 제공합니다.

분산 데이터베이스의 관점에서 Redis Cluster는 파티션 동안 제한된 가용성을 제공하고, 약한 형태의 일관성을 제공합니다. 기본적으로 CP 시스템도 AP 시스템도 아닙니다. 즉, Redis Cluster는 분산 시스템으로서 가능한 이론적 한계를 달성하지 못하는 대신, 특정 현실적 특성을 얻습니다.

일관성 모델은 유명한 '최종 일관성(eventual consistency)' 모델입니다. 기본적으로 파티션 때문에 노드들이 동기화되지 않으면, 파티션이 해소될 때 특정 키를 제공하는 모든 노드가 그 값에 동의하게 됩니다.

그러나 병합 전략은 '마지막 페일오버가 이긴다(last failover wins)'입니다. 따라서 네트워크 파티션 동안 받은 쓰기는 손실될 수 있습니다. 일반적인 예는 클라이언트가 쓰기를 시도하는 소수 파티션에 마스터가 분리되는 경우입니다. 파티션이 해소될 때 파티션의 다수 측에서 슬레이브가 이 마스터를 대체하도록 승격되었다면, 이전 마스터가 받은 쓰기는 손실됩니다.

이는 결과적으로 Redis Cluster가 값 병합을 시도하기 위해 데이터 구조에 메타데이터를 포함할 필요가 없다는 뜻입니다. Redis가 지원하는 멋진 명령과 데이터 구조도 Redis Cluster에서 지원됩니다. 따라서 추가 메모리 오버헤드가 없고, API 제한이 없으며, 값이 포함할 수 있는 요소 수에 제한이 없지만, 파티션 동안 안전성은 낮아집니다.

Redis Cluster와 같이 설계된 시스템에서 노드가 분기하는 것은 좋지 않다는 것을 이해하는 것은 간단합니다. 그래서 시스템은 두 노드가 분기할 확률(및 분기 정도)을 제한하여 이러한 단점을 완화하려고 합니다. 이는 몇 가지 방법으로 달성됩니다:

  1. 파티션의 소수 측은 사용할 수 없게 됩니다.
  2. 복제는 일반적으로 클라이언트에 대한 응답과 슬레이브로의 복제 스트림이 동시에 전송되도록 설계되었습니다.
  3. 여러 슬레이브가 마스터를 페일오버할 수 있을 때, 시스템은 실패한 마스터와 덜 분기된 것으로 보이는 슬레이브를 선택하려고 합니다.

이러한 전략은 시스템의 이론적 속성을 바꾸지는 않지만, 일반적인 Redis Cluster 장애 모드에 대해 더 많은 현실적 보호를 추가합니다.

Redis API와 사용 사례에 있어 이 설계는 합리적이라고 생각하지만, 과거에는 많은 사람들이 동의하지 않았습니다. 그러나 제 의견은 각 설계자는 원하는 대로 시스템을 설계할 자유가 있다는 것입니다. 단 하나의 규칙이 있습니다. 진실을 말하는 것입니다. 그래서 Redis Cluster는 공식 문서에서 한계와 장애 모드를 명확히 문서화합니다.

시스템이 유용한지 여부를 결정하는 것은 사용자와 당면한 사용 사례입니다. 제 느낌으로는 6년 동안 사용자들은 클러스터링 지원이 전혀 없음에도 불구하고 Redis를 계속 사용했습니다. 사용 사례가 이를 가능하게 했고, Redis는 특정 문제를 해결하는 데 매우 적합한 특정 기능과 성능을 제공했기 때문입니다. 제 바람은 Redis Cluster가 그 많은 사용자들의 삶을 개선하는 것입니다.

앞으로의 길

마침내 우리는 출시할 수 있는 최소 기능 제품(MVP)을 갖게 되었습니다. 사용자들이 진지하게 테스트를 시작하고 특정 경우에는 이미 채택할 수 있을 만큼 안정적입니다. 채택이 많아질수록 우리는 더 개선합니다. 저는 Redis와 Sentinel을 통해 이를 알고 있습니다. 이제 소프트웨어를 사용 가능한 상태에서 성숙한 상태로 발전시키는 점진적 프로세스가 있습니다. 사용자의 의견을 듣고, 버그를 수정하고, 더 많은 코드를 테스트로 커버하는 것 등입니다.

동시에 저는 Redis Cluster의 다음 버전을 생각하기 시작했습니다. 지금은 추가할 수 없었던 많은 유용한 기능으로 v1을 개선하는 것입니다. 예를 들어 다중 데이터 센터 지원, 명령 재생을 사용한 소수 파티션에서의 더 나은 쓰기 안전성, 자동 노드 밸런싱(현재는 특정 노드가 너무 비어 있고 다른 노드가 너무 꽉 찬 경우 수동으로 재샤딩해야 합니다) 등이 있습니다.

게다가 저는 Redis Cluster가 캐싱을 위해 특별히 설계된 특수 실행 모드의 혜택을 받을 수 있다고 생각합니다. 이 모드에서는 노드가 담당하지 않는 해시 슬롯에 대한 쓰기를 받아들임으로써 소수 파티션에서도 가용성을 유지합니다.

구현과 설계를 개선하고 수정할 시간은 항상 있습니다. 그러나 소프트웨어가 어떻게 되기를 바라는지에 너무 집중하면, 필요 이상으로 오랫동안 베이퍼웨어 범주에 머물게 할 위험이 있습니다. 이제 놓아줄 때입니다. Redis Cluster를 즐기세요!

Redis Cluster RC1은 Github의 '3.0.0-rc1' 태그 또는 Redis.io 다운로드 페이지(http://redis.io/download)의 tarball로 제공됩니다.

원문은 Salvatore Sanfilippo님이 에 게재했습니다.

이 글은 deepseek-v4-flash 모델을 사용해 번역했습니다.