분산 시스템에서 합의의 필요성
분산 시스템에서는 하나의 중앙 서버가 모든 결정을 내리지 않습니다. 대신 여러 노드가 함께 데이터를 저장하고 처리합니다.
이때 문제가 되는 것은 “어느 노드의 응답을 믿을 것인가?“입니다.
일부 노드가 장애를 일으키거나 서로 다른 데이터를 갖고 있을 때, 시스템은 어떤 기준으로 정답을 결정해야 할까요?
이러한 상황에서 필요한 것이 바로 “합의 알고리즘“이며, 그중 하나가 정족수 합의(quorum-based consensus)입니다.
정족수란?
정족수(quorum)란, 시스템이 올바르게 동작하기 위해 필요한 최소한의 응답 수를 의미합니다. 예를 들어, 세 명이 의사결정을 내리는 회의에서 두 명 이상이 동의해야 결정을 내릴 수 있다면, 그 두 명이 바로 정족수입니다.
분산 시스템에서도 비슷합니다. 노드가 3개 있을 때 2개 이상의 응답이 있어야 데이터가 유효하다고 판단한다면, 그 2개가 정족수가 되는 것입니다.
예시: 노드 A, B, C가 있는 시스템에서 노드 C가 장애를 일으켜도, A와 B가 같은 응답을 보냈다면 이를 정답으로 간주할 수 있습니다. 이처럼 정족수를 만족하는 응답이 있으면 시스템은 계속 동작할 수 있습니다.
정족수 합의의 특징
장점
- 구조가 단순하여 구현이 쉬움
- 일부 노드 장애를 허용하므로 높은 가용성 확보
- 읽기/쓰기 정족수를 조절해 성능을 유연하게 조정 가능
단점
- 네트워크 분할 발생 시 일관성 유지 어려움
- 중복 쓰기나 충돌 상황에서는 복잡한 처리 필요
어떻게 구현되는가?
정족수 합의에서 중요한 수식은 다음과 같습니다.
W + R > N
- N: 전체 노드 수
- W: 쓰기 정족수 (쓰기 시 필요한 응답 수)
- R: 읽기 정족수 (읽기 시 필요한 응답 수)
이 조건이 만족되면 읽기와 쓰기 연산이 최소 한 노드에서 겹치므로 일관성을 확보할 수 있습니다.
예시: N = 3일 때, W = 2, R = 2 라면 항상 최소 한 노드에서 읽기와 쓰기가 교차하므로 최신 데이터를 읽을 수 있습니다.
어떤 시스템에서 사용되나?
DynamoDB, Cassandra 같은 NoSQL 시스템은 정족수 기반의 유연한 일관성 모델을 제공합니다. 예를 들어 Cassandra에서는 클라이언트가 QUORUM
, ONE
, ALL
같은 일관성 수준을 선택할 수 있습니다.
이러한 시스템은 쓰기와 읽기 성능, 지연 시간, 가용성을 조절할 수 있어 대규모 서비스에서 유용하게 사용됩니다.
DynamoDB에서의 정족수 합의 과정
Amazon DynamoDB는 완벽한 일관성을 보장하기보다는 가용성과 확장성을 우선으로 하는 설계 철학을 따릅니다. 이 과정에서 정족수 합의(quorum-based consensus)는 핵심적인 역할을 합니다.
sequenceDiagram participant Client as 클라이언트 participant A as 노드 A participant B as 노드 B participant C as 노드 C (지연) Client->>A: 쓰기 요청 (데이터 X) Client->>B: 쓰기 요청 (데이터 X) Client->>C: 쓰기 요청 (데이터 X) A-->>Client: 쓰기 성공 B-->>Client: 쓰기 성공 Note right of Client: W = 2 → 쓰기 완료 Client->>A: 읽기 요청 Client->>B: 읽기 요청 A-->>Client: 데이터 X B-->>Client: 데이터 X Note right of Client: R = 2 → 읽기 완료, 최신 값 확정
배경: 데이터 복제
Dynamo는 데이터를 여러 노드(또는 파티션)에 복제하여 저장합니다. 일반적으로 N개의 복제본을 유지하며, 이들 중 일부는 읽기/쓰기 요청을 처리하는 데 참여합니다.
쓰기 요청 처리 (W)
- 클라이언트는 데이터를 쓰기 위해 요청을 보냅니다.
- 쓰기 정족수 W는 데이터를 성공적으로 저장해야 하는 노드 수입니다.
- Dynamo는 W개의 노드에 데이터가 저장되면 클라이언트에게 성공을 응답합니다.
- 이때 W < N이면, 일부 노드에는 최신 데이터가 없을 수 있습니다.
예: N = 3, W = 2인 경우 → 3개의 복제본 중 2개에만 쓰기가 성공하면 OK로 간주
읽기 요청 처리 (R)
- 클라이언트가 데이터를 읽기 위해 요청을 보내면, 시스템은 최대 R개의 노드에서 데이터를 조회합니다.
- 응답값들 중 최신 값을 선택하거나 conflict resolution을 수행합니다.
- 읽기 정족수 R이 W와 합쳐서 N보다 크다면, 최소 1개 노드는 최신 값을 반드시 갖고 있으므로 일관성을 확보할 수 있습니다.
W + R > N: 정족수 기반 일관성 보장의 조건
Conflict 해결
Dynamo는 강한 정합성 대신 “eventual consistency"를 선택하기 때문에, 충돌이 발생할 수 있습니다. 이 경우 다음과 같은 방식으로 처리됩니다.
- 각 버전의 데이터를 함께 반환
- 클라이언트가 이를 병합
- 서버 측에서 vector clock을 사용해 자동 병합
DynamoDB 자체는 내부적으로 이런 과정을 완전히 노출하진 않지만, 유사한 원리를 기반으로 하여 요청 처리와 복제, 동기화를 관리하고 있습니다. 개발자는 필요에 따라 “강력한 일관성(ReadConsistency = STRONG)“을 선택해 안전한 읽기도 요청할 수 있습니다.
Paxos, Raft와의 차이점
Paxos나 Raft는 분산 시스템에서 강력한 일관성을 보장하기 위한 합의 알고리즘입니다. 반면 정족수 합의는 어느 정도의 일관성을 포기하고 가용성과 응답 속도를 높이는 데 집중합니다.
글로벌 캐시 시스템에서는 일관성보다는 응답 속도가 중요하므로 정족수 기반 시스템이 적합한 반면, 금융 거래 시스템에서는 Paxos나 Raft가 더 적합합니다.
마무리
정족수 합의는 모든 시스템에 적합하진 않지만, 다음과 같은 경우에 효과적일 수 있습니다.
- 약간의 일관성 손해를 감수하더라도 빠른 응답과 높은 가용성이 필요한 경우
- 네트워크가 불안정하거나 노드 장애가 자주 발생하는 환경
정족수 기반 합의는 완벽한 정답을 요구하지 않고, 일부 노드의 응답만으로도 시스템을 안정적으로 운영할 수 있게 해주는 현실적인 접근 방법입니다.