Post

[분산 시스템] Day 2: 복제 - 데이터를 여러 곳에 두는 전략과 대가

[분산 시스템] Day 2: 복제 - 데이터를 여러 곳에 두는 전략과 대가

이 글은 AI(Claude)의 도움을 받아 작성하고, 작성자가 검토·편집했습니다.

서론: 왜 데이터를 여러 곳에 두는가

데이터를 복제하는 이유는 세 가지다. 한 노드가 죽어도 살아남기 위해(가용성), 사용자 가까이에 두기 위해(지연), 읽기 부하를 분산하기 위해(확장성)다. 하지만 복제본이 둘 이상이면 “어느 것이 진실인가”라는 문제가 생긴다. Day 1의 합의가 그 극단적 해법이라면, 오늘은 더 실용적인 복제 전략의 스펙트럼을 본다.

1. 리더-팔로워 복제

가장 흔한 모델. 한 노드가 리더(쓰기 담당), 나머지가 팔로워(복제본)다.

1
2
3
쓰기 → [Leader] ──복제──> [Follower 1]
                  ──복제──> [Follower 2]
읽기 ← Leader 또는 Follower (읽기 부하 분산)
  • 모든 쓰기는 리더로. 리더가 변경을 팔로워에 전파.
  • 읽기는 어느 노드에서나 가능 → 읽기 확장에 유리.
  • PostgreSQL, MySQL, MongoDB, Redis가 기본으로 쓰는 모델.

2. 동기 vs 비동기 복제

리더가 “언제 쓰기 성공을 응답하는가”가 핵심 트레이드오프다.

1
2
3
4
5
6
7
8
9
동기 복제:
  리더가 팔로워의 기록 확인까지 기다린 뒤 클라이언트에 성공 응답
  ✅ 팔로워가 항상 최신 → 리더 장애 시 데이터 손실 없음
  ❌ 팔로워가 느리거나 죽으면 쓰기 전체가 막힘

비동기 복제:
  리더가 자기 기록 후 즉시 응답, 복제는 백그라운드로
  ✅ 빠르고 팔로워 장애에 영향 없음
  ❌ 리더가 죽으면 아직 복제 안 된 쓰기는 유실

현실적 절충은 반동기(semi-sync)다. “최소 한 개의 팔로워만 동기 확인”하면, 모든 팔로워를 기다리지 않으면서도 단일 노드 손실엔 안전하다.

3. 복제 지연이 낳는 이상 현상

비동기 복제에서는 팔로워가 리더보다 뒤처진다(replication lag). 이때 세 가지 읽기 이상이 생긴다.

1
2
3
4
5
6
7
8
1. 자기 쓰기를 못 읽음 (read-your-writes 위반)
   사용자가 프로필 수정 → 뒤처진 팔로워에서 읽음 → 옛날 값이 보임

2. 시간이 거꾸로 감 (monotonic reads 위반)
   첫 읽기는 최신 팔로워, 둘째 읽기는 더 뒤처진 팔로워 → 데이터가 사라진 듯

3. 인과관계 역전 (consistent prefix 위반)
   질문보다 답변이 먼저 보임

해법: 자기가 쓴 데이터는 리더에서 읽기(read-your-writes), 한 사용자는 같은 복제본에 고정(monotonic reads), 인과 관계 추적 등. 일관성 보장은 공짜가 아니라 추가 설계다.

4. 다중 리더 복제

여러 데이터센터에 각각 리더를 두는 모델. 지역별 쓰기 지연을 줄이지만 충돌이 생긴다.

1
2
3
4
[DC1 Leader] ←──양방향 복제──→ [DC2 Leader]
  사용자 A가 DC1에서 x=1          사용자 B가 DC2에서 x=2
                  ↓ 복제 시 충돌
            "x는 1인가 2인가?"

쓰기 충돌 해결 전략:

  • LWW(Last Write Wins): 타임스탬프 큰 쪽 채택. 간단하지만 데이터 유실.
  • 버전 벡터: 충돌을 감지해 애플리케이션이 병합(예: 장바구니 합치기).
  • CRDT: 수학적으로 충돌 없이 병합되도록 설계된 자료구조.

5. 리더 없는 복제 (Dynamo 스타일)

리더 없이 클라이언트가 여러 노드에 직접 읽고 쓴다. Cassandra, DynamoDB의 모델이다.

1
2
3
4
5
6
7
정족수 공식: W + R > N 이면 강한 일관성 경향

N=3 (복제본 수)
  W=2 (쓰기 시 2개 노드 확인), R=2 (읽기 시 2개 노드 조회)
  → W+R=4 > 3 → 읽기와 쓰기 정족수가 최소 1개 노드에서 겹침 → 최신값 포함

  W=1, R=1 → 빠르지만 W+R=2 ≤ 3 → 오래된 값 읽을 수 있음

WR를 조절해 일관성과 지연을 튜닝한다. 충돌은 읽기 복구(read repair)와 버전 벡터로 처리한다.

6. 어떤 복제를 언제 쓰는가

1
2
3
4
리더-팔로워 + 반동기   → 대부분의 OLTP. 강한 일관성 + 단일 리전.
다중 리더            → 다중 데이터센터 쓰기. 충돌 해결 설계 필수.
리더 없음            → 초고가용성, 쓰기 항상 받아야 할 때. 약한 일관성 감수.
합의(Raft, Day 1)    → 설정·메타데이터처럼 절대 틀리면 안 되는 소량 데이터.

원칙: 데이터의 일관성 요구가 셀수록 합의·동기 쪽으로, 가용성·지연이 중요할수록 비동기·리더 없음 쪽으로 간다. 한 시스템 안에서도 데이터 종류별로 다르게 적용한다.

7. Day 2 체크리스트

  1. 복제의 세 목적(가용성·지연·읽기 확장)을 구분했다.
  2. 동기/비동기/반동기 복제의 트레이드오프를 이해했다.
  3. 복제 지연이 낳는 세 가지 읽기 이상과 대응책을 안다.
  4. 다중 리더의 쓰기 충돌과 해결 전략(LWW·버전벡터·CRDT)을 파악했다.
  5. 리더 없는 복제의 W+R>N 정족수 튜닝을 이해했다.

다음 편 예고

복제는 같은 데이터의 사본을 늘리는 것이다. 하지만 데이터가 한 노드에 다 안 들어가면? Day 3에서는 데이터를 쪼개 나눠 담는 파티셔닝(샤딩)과 리밸런싱, 핫스팟 문제를 다룬다.

This post is licensed under CC BY 4.0 by the author.