← 문제로

19. 분산 합의(Consensus): Raft·Paxos 기초와 게임 서버 메타데이터 관리

난이도 상
내 답안
모범답안

난이도: 상

모범 답안

1. 왜 합의가 필요한가

단일 DB/단일 리더는 SPOF다 — 그 노드가 죽으면 "누가 존을 소유하는가" 같은 결정을 아무도 내리지 못해 서비스가 멈춘다. 그렇다고 여러 노드가 각자 결정하면 split-brain: 두 코디네이터가 동시에 자신을 리더로 믿고 같은 존을 서로 다른 게임 노드에 배정하면, 한 플레이어가 두 노드에서 활성화되어 아이템 복사·상태 충돌·이중 과금이 발생한다. 합의는 "여러 노드가 죽거나 네트워크가 끊겨도 하나의 일관된 결정에 도달"하게 해, 가용성과 정합성을 동시에 확보한다.

2. 복제 상태 머신

핵심 아이디어: 모든 노드를 결정적 상태 머신으로 보고, 동일한 명령 로그동일한 순서로 적용하면 모두 같은 상태에 도달한다. 그래서 합의의 실체는 "값 하나에 합의"가 아니라 "로그의 각 슬롯에 어떤 명령이 들어갈지에 순서대로 합의" 하는 것이다. 로그가 일치하면 상태도 일치한다. (예: assign(zone7, nodeB), set_config_version(42) 같은 명령을 순서대로 복제·적용.)

3. Raft

  • 리더 선출: 시간을 term(임기) 으로 나눈다. 팔로워가 리더의 하트비트를 랜덤 선거 타임아웃 동안 못 받으면 후보가 되어 term을 올리고 투표를 요청한다. 과반수 표를 얻으면 리더가 된다. 랜덤 타임아웃이 동시 후보(선거 분열)를 확률적으로 깨서 대개 빠르게 한 리더로 수렴한다.
  • 로그 복제: 클라이언트 명령은 리더만 받는다. 리더는 자기 로그에 추가하고 AppendEntries 로 팔로워에 복제한다. 어떤 엔트리가 과반수 노드에 복제되면 커밋(commit) 되고, 그때 상태 머신에 적용한다. 커밋된 엔트리는 절대 뒤집히지 않는다.
  • 안전성: 투표 시 후보의 로그가 자신보다 최신(마지막 term·인덱스 비교) 일 때만 표를 준다. 그래서 커밋된 엔트리를 갖지 못한 오래된 후보는 당선될 수 없다(Leader Completeness).
  • 왜 과반수(quorum, ⌊N/2⌋+1)? 임의의 두 과반수 집합은 반드시 한 노드 이상에서 겹친다. 이 교집합이 "이전에 커밋된 정보"를 다음 리더에게 반드시 전달해, 두 개의 상충하는 결정이 동시에 커밋되는 것을 막는다(split-brain 방지). 5노드면 과반수는 3이므로 2대 장애까지 정상 동작한다(3노드는 1대, 7노드는 3대). 과반수를 못 채우면 진행을 멈춘다 — 가용성보다 안전성을 택한다.

4. Paxos와의 관계

  • Basic Paxos: 단일 값 하나에 합의하는 알고리즘(prepare/promise → accept/accepted, 과반수 기반). 올바르지만 값 하나짜리라 실무엔 그대로 못 쓴다.
  • Multi-Paxos: 안정적 리더를 두고 Basic Paxos를 로그 슬롯마다 반복해 로그 복제로 확장한 것.
  • Raft: 결과적으로 Multi-Paxos와 등가의 보장을 주되 이해 가능성을 목표로 설계됐다. 강한 리더 (모든 로그 흐름이 리더 → 팔로워 단방향)와 로그 연속성(구멍 없는 연속 로그, term으로 정렬)으로 구조를 단순화해, Paxos의 난해한 부분을 걷어냈다. 실무 시스템(etcd, Consul, TiKV 등)이 Raft를 많이 쓴다.

5. CAP·성능·실무

  • CAP: 합의 시스템은 CP다. 네트워크 파티션으로 과반수를 확보 못 하는 쪽(소수파)은 쓰기(및 선형화 읽기)를 거부해 일관성을 지킨다 — 즉 파티션 시 가용성을 포기한다.
  • 비용: 모든 커밋이 과반수 왕복(디스크 fsync + 네트워크) 을 요구해 지연·처리량 한계가 뚜렷하다. 초당 수만~수십만 건의 플레이어 이동/전투 상태를 합의로 넣으면 절대 못 버틴다.
  • 게임 서버 권고: 합의는 드물게 바뀌지만 반드시 일관돼야 하는 것에만 쓴다 — 존 소유권·리더십 (누가 매치메이킹/스케줄러 리더인가)·구성 버전·샤드 매핑·분산 락의 근간. 반대로 고빈도 플레이어 상태는 합의 밖에서 처리하고, 소유권만 합의로 정한 뒤 그 소유 노드가 자기 존의 상태를 단독으로 관리한다(합의는 "누가 쓸 수 있는가"만 정하고, 실제 쓰기는 그 노드가 로컬로). 리스/펜싱 토큰을 합의로 발급해 옛 소유자의 늦은 쓰기를 무효화하면 split-brain을 막는다.
  • 도구: 직접 Raft를 구현하기보다 etcd/ZooKeeper/Consul 같은 검증된 합의 저장소에 리더 선출 (리스·세션), 서비스 디스커버리, 구성/멤버십을 맡기고, 게임 로직은 그 위에서 소유권·펜싱만 받아쓴다.

핵심 요약

합의는 "장애가 나도 하나의 일관된 결정"을 만드는 복제 상태 머신이며, Raft는 강한 리더·과반수 커밋· 로그 최신성 규칙으로 split-brain을 막는다. 과반수의 교집합이 안전성의 핵심이고, N=5면 2대 장애를 견딘다. 합의는 CP이자 비싸므로 메타데이터·리더십·구성에만 쓰고 고빈도 플레이어 상태는 소유권+펜싱으로 분리하는 것이 게임 서버의 정석이다. 실무에선 etcd/ZooKeeper를 활용한다.