2 minute read

복제는 네트워크를 통해 연결된 여러 컴퓨터에 동일한 데이터의 복사본을 보관하는 것을 말한다. 데이터를 복제해야 하는 이유는 여러 가지가 있다:

  • 지연 시간을 줄이려는 경우, 데이터를 사용자와 지리적으로 가깝게 유지한다.
  • 가용성을 높이려는 경우, 일부 부품에 장애가 발생하더라도 시스템이 계속 작동할 수 있도록 한다.
  • 읽기 처리량을 늘리려면, 읽기 쿼리를 처리할 수 있는 컴퓨터의 수를 확장한다.

데이터 복제에는 두 가지 경우를 가정해야 한다.

  • 데이터 세트가 너무 작아서 각 머신이 전체 데이터 세트의 복사본을 보유할 수 있음
  • 단일 머신에서 처리하기에는 너무 큰 데이터 세트의 파티셔닝(샤딩)

복제하는 데이터가 시간이 지나도 변경되지 않는다면, 모든 노드에 데이터를 한 번만 복사하면 복제가 완료되므로 복제가 쉽다. 복제의 모든 어려움은 복제된 데이터의 변경 사항을 처리하는 데 있다.

노드 간에 변경 사항을 복제하는 데 널리 사용되는 알고리즘은 세 가지가 있다.

  • 단일 리더
  • 멀티 리더
  • 리더리스 복제

데이터 복제시에 고려해야할 절충점

  • 동기식 복제
  • 비동기식 복제

데이터베이스 복제는 오래된 주제이며, 네트워크의 근본적인 제약 조건이 변하지 않았기 때문에 1970년대에 연구된 이래 원칙은 크게 변하지 않았다. 그러나 연구 외적으로 많은 개발자는 오랫동안 데이터베이스가 하나의 노드로만 구성되어 있다고 가정해 왔다. 분산 데이터베이스가 주류로 사용되기 시작한 것은 최근의 일이다.

복제는 왜 까다로운가?

  • 복제는 동시성과 잘못될 수 있는 모든 사항에 대해 신중하게 고려하고 오류의 결과를 처리해야 한다.
  • 최소한 노드를 사용할 수 없는 경우와 네트워크 중단에 대처해야 합니다(소프트웨어 버그로 인한 소리 없는 데이터 손상과 같은 더 교묘한 종류의 오류는 고려하지 않은 것입니다).

복제를 위한 세 가지 주요 접근 방식

단일 리더 복제

클라이언트는 모든 쓰기를 단일 노드(리더)로 보내고, 이 노드는 데이터 변경 이벤트 스트림을 다른 복제본(팔로워)으로 보낸다. 읽기는 모든 복제본에서 수행할 수 있지만 팔로워의 읽기는 오래되었을 수 있다.

단일 리더 복제는 이해하기 쉽고 충돌 해결에 대해 걱정할 필요가 없기 때문에 널리 사용된다.

멀티리더 복제

클라이언트는 각 쓰기를 여러 리더 노드 중 하나에 보내며, 이 중 어느 노드든 쓰기를 수락할 수 있다. 리더 노드는 데이터 변경 이벤트 스트림을 서로에게 그리고 모든 팔로워 노드에게 보낸다.

리더 없는 복제

클라이언트는 오래된 데이터가 있는 노드를 감지하고 수정하기 위해 각 쓰기를 여러 노드에 보내고, 여러 노드에서 동시에 읽는다.

멀티리더 및 리더없는 복제는 결함이 있는 노드, 네트워크 중단, 지연 시간 급증이 있는 경우 강력할 수 있지만, 추론하기가 어렵고 일관성이 약하게 보장되는 대신에 안정적일 수 있다.

동기식 복제 및 비동기식 복제

복제는 동기식 또는 비동기식일 수 있으며, 장애가 발생했을 때 시스템 동작에 큰 영향을 미친다. 시스템이 원활하게 작동할 때는 비동기 복제가 빠를 수 있지만, 복제 지연이 증가하거나 서버에 장애가 발생하면 어떤 일이 발생하는지 파악하는 것이 중요하다. 리더가 실패하고 비동기식으로 업데이트되는 팔로워를 새 리더로 승격하면 최근에 커밋한 데이터가 손실될 수 있다.

복제 지연시 도움이 되는 일관성 모델

  • 읽기 후 쓰기 일관성 (Read-after-write consistency) 사용자는 항상 자신이 직접 제출한 데이터를 볼 수 있어야 한다.

  • 단조로운 읽기 (monotonic reads) 사용자가 한 시점에 데이터를 본 후에는 나중에 이전 시점의 데이터를 볼 수 없어야 한다.

  • 일관된 접두사 읽기 (Consistent prefix reads) 사용자는 인과관계가 맞는 상태에서 데이터를 볼 수 있어야 한다. 예를 들어, 질문과 그에 대한 답변이 올바른 순서로 표시되어야 한다.

동시성 문제

다중 리더 및 리더리스 복제 방식은 여러 번의 쓰기를 허용하기 때문에 현재 충돌이 발생할 수 있다.

이를 해결하기 위한 방법은

  • 데이터베이스에서 한 작업이 다른 작업보다 먼저 발생했는지 또는 동시에 수행되었는지 여부를 판단하는 데 사용할 수 있는 알고리즘
  • 동시 업데이트를 병합하여 충돌을 해결하는 방법