Skip to content

✍️ 필사 모드: DB 샤딩 & 파티셔닝 완전 가이드 2025: 수평 확장, Range/Hash/Directory, 리샤딩, Vitess

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

TL;DR

  • 샤딩 = 수평 확장의 답: 단일 DB로 안 되는 규모에서 필수
  • 샤드 키 선택이 운명: 잘못 선택하면 hot spot, 재샤딩 지옥
  • 3대 전략: Range, Hash, Directory (Lookup) — 각각 장단점
  • 분산 트랜잭션이 어려움: 2PC는 느림, Saga가 현실적
  • Vitess가 표준: YouTube/Slack/GitHub이 사용. MySQL 위의 분산 레이어

1. 샤딩이란?

1.1 단일 DB의 한계

[Single DB]
  ├─ CPU: 1 머신만큼만
  ├─ RAM: 256GB? 512GB?
  ├─ 디스크: 30TB
  └─ 네트워크: 25 Gbps

→ 결국 한계에 도달

수직 확장 (Vertical Scaling):

  • 더 큰 머신
  • 한계 있음 (가장 큰 EC2 = 24TB RAM, $20+/시간)
  • 단일 장애점

수평 확장 (Horizontal Scaling):

  • 여러 머신
  • 무한 확장
  • 복잡도 증가

1.2 Read Replica로 해결?

[Primary] (쓰기)
   ↓ replication
[Replica 1] [Replica 2] [Replica 3] (읽기)

도움: 읽기 트래픽 분산.

한계: 쓰기는 여전히 Primary 1대. 쓰기가 병목이면 도움 안 됨.

샤딩이 필요합니다.

1.3 샤딩의 정의

샤딩 = 데이터를 여러 독립적 DB(샤드)에 분산.

[users 테이블]
  ↓ shard by user_id
[Shard 1: user_id 1-1M]
[Shard 2: user_id 1M-2M]
[Shard 3: user_id 2M-3M]
...

각 샤드는 완전히 독립적인 DB. 자체 CPU, RAM, 디스크.

1.4 샤딩의 효과

단일 DB100 샤드
데이터1 TB100 TB
쓰기 TPS10,0001,000,000
비용$10K/월$50K/월
복잡도낮음매우 높음

100배 성능 + 5배 비용 = ROI 좋음. 단, 복잡도가 큰 문제.


2. 샤드 키 선택 — 가장 중요한 결정

2.1 좋은 샤드 키의 조건

  1. 균등 분포 — 데이터가 모든 샤드에 균등 분산
  2. 불변 — 한 번 정해지면 거의 안 변함
  3. 쿼리 패턴 일치 — 자주 함께 조회되는 데이터는 같은 샤드
  4. 카디널리티 높음 — 충분히 많은 고유 값
  5. 단조 증가 X — auto-increment ID는 hot spot 위험

2.2 흔한 샤드 키 후보

user_id:

  • ✅ 사용자 데이터를 한 샤드에 모음 (관련 데이터 같이)
  • ❌ 큰 사용자가 hot spot
  • ❌ user 간 JOIN 어려움

created_at:

  • ❌ 단조 증가 → 모든 새 데이터가 한 샤드에 (hot spot)
  • 시계열 데이터에는 OK

hash(id):

  • ✅ 균등 분포
  • ❌ 범위 쿼리 불가능
  • ❌ 관련 데이터가 다른 샤드

country:

  • ✅ Geographic 효율
  • ❌ 매우 불균등 (US가 거대, 모나코는 작음)

organization_id:

  • ✅ B2B SaaS에 이상적
  • ❌ 큰 조직이 hot spot

2.3 Slack의 사례

Slack의 샤드 키 = workspace_id.

이유:

  • 같은 workspace의 모든 데이터를 한 샤드에 → 빠른 조회
  • workspace 간 JOIN 거의 없음
  • workspace 단위로 자연스러운 격리

단점: 거대 enterprise workspace가 단일 샤드 압도 → "Whale shard" 문제.

해결: 거대 workspace는 자체 전용 샤드.


3. 샤딩 전략

3.1 Range Sharding

데이터를 키의 범위로 분할.

Shard 1: id 1 ~ 1,000,000
Shard 2: id 1,000,001 ~ 2,000,000
Shard 3: id 2,000,001 ~ 3,000,000

장점:

  • 범위 쿼리 효율 (WHERE id BETWEEN 500000 AND 600000)
  • 단순한 라우팅
  • 새 샤드 추가 쉬움

단점:

  • Hot spot 위험: 단조 증가 키면 새 데이터가 모두 마지막 샤드에
  • 불균등 분포 가능

사용 사례: 시계열 데이터, BigTable, HBase

3.2 Hash Sharding

샤드 키의 hash로 분할.

shard_id = hash(user_id) % num_shards

장점:

  • 균등 분포 — hash가 잘 만들어졌으면
  • 단조 증가 키도 안전

단점:

  • 범위 쿼리 불가능 (WHERE id BETWEEN ...)
  • 새 샤드 추가 시 거의 모든 데이터 재분배 (% num_shards가 변하니까)

해결: Consistent Hashing — 샤드 추가/제거 시 일부 데이터만 이동.

3.3 Consistent Hashing

[원형 해시 공간]
        Shard A
       /
  Shard D
       \
        Shard B
       /
  Shard C

각 샤드와 데이터를 같은 해시 공간에 매핑. 데이터는 시계방향으로 가장 가까운 샤드에.

샤드 추가 시: 해당 부분만 재분배 (전체의 1/N).

Virtual Nodes: 각 샤드를 여러 가상 노드로 표현 → 더 균등.

사용: Cassandra, DynamoDB, Riak, Memcached.

3.4 Directory-Based Sharding

Lookup 테이블로 어떤 데이터가 어떤 샤드에 있는지 명시적 매핑.

[Lookup]
user_1 → Shard A
user_2 → Shard B
user_3 → Shard A
...

장점:

  • 유연: 임의의 매핑 가능
  • 균등하지 않은 분포도 처리
  • 마이그레이션 쉬움

단점:

  • Lookup 자체가 병목 (캐싱 필수)
  • 추가 인프라 (Redis, Consul)
  • 단일 장애점

사용: Vitess (이런 방식의 변형)

3.5 Geographic Sharding

위치별 샤드:

  • US 사용자 → US 샤드
  • EU 사용자 → EU 샤드
  • Asia 사용자 → Asia 샤드

장점:

  • 사용자에 가까이 → 낮은 latency
  • 규제 준수 (GDPR — EU 데이터를 EU에)
  • 자연스러운 분할

단점:

  • 사용자 이동 시 어려움
  • 글로벌 쿼리 어려움
  • 매우 불균등 (지역별 사용자 수)

3.6 비교표

전략균등성범위 쿼리추가쿼리 패턴
Range낮음쉬움범위
Hash높음어려움정확
Consistent Hash높음쉬움정확
Directory높음부분쉬움자유
Geographic낮음부분보통지역

4. Hot Spot 문제

4.1 Hot Spot이란?

특정 샤드에 트래픽/데이터가 집중되는 현상.

원인:

  • 잘못된 샤드 키 (인기 사용자, 인기 상품)
  • 단조 증가 키 (created_at)
  • 불균등 분포 (몇몇 거대 조직)

4.2 영향

[Shard 1: 10% 트래픽]
[Shard 2: 5% 트래픽]
[Shard 3: 80% 트래픽]Hot spot! 죽음
[Shard 4: 5% 트래픽]

전체 시스템이 가장 약한 샤드에 의해 결정됩니다.

4.3 탐지

-- 샤드별 데이터 양
SELECT shard_id, COUNT(*) as row_count
FROM users
GROUP BY shard_id;

-- 샤드별 쿼리 수 (애플리케이션 메트릭)

경고 신호:

  • 한 샤드가 평균보다 5배+ 큼
  • 한 샤드의 CPU/IO가 100%

4.4 해결책

1. 샤드 키 변경

  • 가장 좋지만 가장 어려움 (재샤딩 필요)

2. Composite Key

shard_key = hash(user_id + timestamp_bucket)

시간 기반 + 사용자 기반 결합.

3. 하위 샤딩 (Sub-sharding)

  • Hot 샤드를 더 잘게 분할
  • "Whale shard" 처리

4. 캐싱

  • 핫 데이터를 Redis로
  • DB 부하 감소

5. 읽기 복제본

  • 읽기 부하 분산
  • 쓰기는 여전히 hot

4.5 예시: Twitter의 Celebrity Problem

문제: 한 셀럽 사용자(예: 일론 머스크)가 트윗 → 수억 followers의 timeline 업데이트.

해결:

  • Fan-out on write (일반 사용자): 트윗 시 followers의 timeline에 미리 작성
  • Fan-in on read (셀럽): 트윗 시 timeline 안 만듦, 읽을 때 가져옴
  • 하이브리드: 활성 followers는 fan-out, 비활성은 fan-in

5. 분산 쿼리의 어려움

5.1 단일 샤드 쿼리

SELECT * FROM users WHERE user_id = 12345;

→ user_id로 샤드 결정 → 해당 샤드만 쿼리. 매우 빠름.

5.2 Cross-Shard 쿼리

SELECT COUNT(*) FROM users WHERE country = 'KR';

모든 샤드에 쿼리 → 결과 합산. 느림 + 부하.

5.3 JOIN의 어려움

SELECT u.name, o.total
FROM users u
JOIN orders o ON o.user_id = u.user_id
WHERE u.country = 'KR';

users와 orders가 다른 샤드에 있으면? 분산 JOIN 필요.

전략:

  1. Co-location: 같은 user_id의 users와 orders를 같은 샤드에
  2. Denormalization: orders에 user 정보 복사
  3. 분산 쿼리 엔진: Vitess, Citus가 자동 처리
  4. CQRS: 쿼리용 별도 DW (Snowflake) 사용

5.4 분산 트랜잭션

def transfer(from_user, to_user, amount):
    # 두 사용자가 다른 샤드에 있을 수 있음
    db.update(f"... WHERE user_id={from_user}", -amount)
    db.update(f"... WHERE user_id={to_user}", +amount)

문제: 첫 update 성공 + 두 번째 실패 → 돈 사라짐.

해결:

1. 2PC (Two-Phase Commit):

  • Prepare → Commit
  • 모든 샤드가 동의해야 commit
  • 느림 + 단일 장애점 → 비추천

2. Saga 패턴:

  • 보상 트랜잭션
  • Eventually consistent
  • 실전 표준

3. 같은 샤드에 보장:

  • 가능하면 전송자/수신자를 같은 샤드에
  • 항상 가능하지는 않음

6. 리샤딩 — 가장 무서운 작업

6.1 왜 리샤딩이 어려운가?

  • 데이터 이동: 수십 TB 이동
  • 무중단: 사용자 영향 X
  • 롤백: 문제 시 복구
  • 일관성: 이동 중 쓰기/읽기 처리

6.2 리샤딩 시나리오

1. 샤드 추가: 4 샤드 → 8 샤드 2. 샤드 분할: 거대 샤드를 둘로 3. 샤드 병합: 작은 샤드 합치기 4. 샤드 키 변경: 가장 어려움

6.3 리샤딩 패턴

1. Bulk Copy + Switchover:

  1. 새 샤드에 데이터 복사
  2. 짧은 maintenance window
  3. 트래픽 전환
  4. 옛 샤드 삭제

단점: 다운타임.

2. CDC + Dual Write:

  1. CDC로 옛 → 새 샤드 동기화
  2. 애플리케이션이 옛 + 새 둘 다 쓰기 (dual write)
  3. 데이터 일치 확인
  4. 읽기를 새로 전환
  5. 옛 샤드 폐기

무중단, 복잡.

3. Online Migration:

  • Vitess의 VReplication
  • 자동화된 무중단 마이그레이션
  • 진행률 모니터링

6.4 사례: Slack의 샤딩 진화

  • 2017: 단일 MySQL → 복제본
  • 2018: 첫 샤딩 (workspace_id)
  • 2020: Vitess 도입
  • 2022: Whale workspace 처리
  • 2024: 수천 샤드, 페타바이트

교훈: 샤딩은 한 번에 끝나지 않음. 지속적 진화.


7. Vitess — MySQL 위의 분산 레이어

7.1 Vitess란?

YouTube가 만든 MySQL 샤딩 솔루션. CNCF 졸업.

[Client]
[VTGate] (쿼리 라우터)
[VTTablet] [VTTablet] [VTTablet]
   ↓        ↓          ↓
[MySQL]  [MySQL]    [MySQL]

장점:

  • MySQL 호환 — 기존 코드 그대로
  • 자동 샤딩 — 키 기반 라우팅
  • 스키마 마이그레이션 — 안전한 DDL
  • VReplication — 무중단 리샤딩
  • 검증된 규모 — YouTube, Slack, GitHub, Square

7.2 사용 회사

  • YouTube (창시자, 페타바이트)
  • Slack (대규모)
  • GitHub (MySQL → Vitess 전환)
  • Square
  • Pinterest
  • JD.com (중국 최대 e-commerce)

7.3 VSchema 예시

{
  "sharded": true,
  "vindexes": {
    "hash": {
      "type": "hash"
    }
  },
  "tables": {
    "users": {
      "column_vindexes": [
        {
          "column": "user_id",
          "name": "hash"
        }
      ]
    }
  }
}

→ VTGate가 자동으로 user_id 기반 샤딩.


8. 다른 분산 DB 옵션

8.1 Citus (PostgreSQL)

PostgreSQL 확장. 분산 쿼리, 분산 트랜잭션 지원.

SELECT create_distributed_table('events', 'user_id');

장점: PostgreSQL 호환, SQL 그대로. 단점: PostgreSQL 한계 (Vitess보다 성숙도 낮음).

8.2 CockroachDB

처음부터 분산 SQL DB로 설계.

장점:

  • PostgreSQL 호환
  • 자동 샤딩 (range-based)
  • 글로벌 분산 지원
  • 분산 ACID 트랜잭션

단점:

  • 일부 PG 기능 미지원
  • 더 비싼 운영
  • 학습 곡선

사용: DoorDash, Bose, Comcast.

8.3 YugabyteDB

CockroachDB와 비슷. PostgreSQL 호환 + Cassandra 호환 동시.

8.4 TiDB

MySQL 호환 + 자동 분산. 중국에서 인기.

8.5 비교표

VitessCitusCockroachDBYugabyteDBTiDB
기반MySQLPostgreSQL자체자체자체
호환성MySQLPostgreSQLPostgreSQLPG + CQLMySQL
분산 트랜잭션제한
자동 샤딩수동 키수동 키자동자동자동
운영 난이도보통낮음보통보통보통
검증YouTube, Slack다수DoorDash다수중국 큰 회사

9. 실전 — e-commerce 샤딩 설계

9.1 시나리오

  • 1억 사용자
  • 일일 1000만 주문
  • 단일 PostgreSQL 한계 도달

9.2 분석

테이블:

  • users (1억 행)
  • orders (10억 행)
  • products (100만 행)
  • reviews (50억 행)

9.3 샤딩 결정

1. users:

  • 샤드 키: user_id (hash)
  • 16개 샤드
  • 균등 분포

2. orders:

  • 샤드 키: user_id (hash, users와 같은 샤드)
  • 같은 사용자의 user + orders가 같은 샤드 → JOIN 빠름

3. products:

  • 작음 (100만 행)
  • 샤딩 X — 단일 DB + 읽기 복제본
  • 또는 모든 샤드에 복제

4. reviews:

  • 샤드 키: product_id (hash)
  • product 기준 분석에 적합

9.4 쿼리 패턴

-- 사용자 주문 (같은 샤드)
SELECT * FROM orders WHERE user_id = 12345;
-- ✅ 빠름

-- 사용자 정보 + 주문 (같은 샤드, JOIN OK)
SELECT u.*, o.*
FROM users u JOIN orders o ON o.user_id = u.user_id
WHERE u.user_id = 12345;
-- ✅ 빠름

-- 제품 리뷰 (다른 샤드)
SELECT * FROM reviews WHERE product_id = 67890;
-- ✅ 빠름

-- 사용자가 작성한 모든 리뷰 (cross-shard)
SELECT * FROM reviews WHERE user_id = 12345;
-- ⚠️ 느림 — 모든 reviews 샤드 검색

-- 해결: 비정규화. users 샤드에도 review 요약 저장.

9.5 인프라

[Application]
[ProxySQL / Vitess]
[16 user shards]
[16 order shards (co-located)]
[1 products DB + 5 read replicas]
[8 reviews shards]

9.6 모니터링

  • 샤드별 쿼리 수
  • 샤드별 디스크 사용량
  • Cross-shard 쿼리 비율
  • Hot spot 탐지

10. 샤딩의 함정과 교훈

10.1 너무 일찍 샤딩

잘못된 결정: 트래픽이 1000 QPS인데 샤딩.

현실:

  • 단일 PostgreSQL = 50,000 QPS+
  • Read replica = 200,000 QPS+
  • 적절한 인덱스 + 캐싱 = 더 많이

샤딩 전에 다른 모든 최적화를 먼저 시도하세요.

10.2 잘못된 샤드 키

GitHub의 첫 샤딩 시도가 실패한 사례:

  • repo_id로 샤딩 → 인기 repo가 hot spot
  • Linus의 linux 저장소가 단일 샤드 압도
  • 재샤딩 필요 (수개월의 작업)

교훈: 샤드 키는 변경하기 매우 어렵다. 처음에 신중히.

10.3 분산 트랜잭션 회피

분산 트랜잭션은 정말 어려움. 가능한 한 같은 샤드 안에서만 트랜잭션 보장.

설계 시: 쓰기 트랜잭션이 항상 단일 샤드 안에 들어가도록 데이터 모델 설계.

10.4 운영 복잡도

샤딩한 시스템은:

  • 백업 복잡 (16개 샤드 동시)
  • 모니터링 복잡
  • 디버깅 어려움 (어느 샤드?)
  • 마이그레이션 어려움

자동화 필수. 운영 인력 충분히.

10.5 NewSQL이 답?

CockroachDB, YugabyteDB 같은 NewSQL은 자동 샤딩 + 분산 트랜잭션. 수동 샤딩의 복잡도 없음.

언제 NewSQL?:

  • 새 프로젝트
  • 강한 일관성 필요
  • 운영 인력 부족

언제 수동 샤딩?:

  • 기존 MySQL/PostgreSQL
  • 극단적 성능 필요
  • NewSQL 성숙도 우려

퀴즈

1. 샤딩이 read replica로 해결할 수 없는 이유는?

: Read replica는 읽기만 분산합니다. 쓰기는 여전히 Primary 1대가 처리. 쓰기가 병목인 시스템 (예: 일일 10억 INSERT)은 read replica로 해결 불가능. 샤딩만이 쓰기를 여러 머신에 분산할 수 있습니다. 단, 샤딩은 복잡도가 매우 높으므로 read replica + 캐싱 + 인덱스 최적화로 해결 가능한지 먼저 검토해야 합니다.

2. Hash sharding의 장단점은?

: 장점: 균등 분포 (hash가 잘 만들어졌으면). 단조 증가 키도 안전. 단점: 범위 쿼리 불가능 (WHERE id BETWEEN ...). 샤드 추가 시 거의 모든 데이터 재분배 (% num_shards가 변하므로). 해결책: Consistent Hashing — 샤드 추가/제거 시 일부 데이터(1/N)만 이동. Cassandra, DynamoDB, Riak가 사용. Virtual nodes로 더 균등한 분포.

3. Hot Spot 문제를 어떻게 해결하나요?

: (1) 샤드 키 변경 — 가장 좋지만 재샤딩 필요 (어려움), (2) Composite keyhash(user_id + timestamp_bucket)로 시간/사용자 분산, (3) 하위 샤딩 — Hot 샤드를 더 잘게 분할 ("whale shard"), (4) 캐싱 — 핫 데이터를 Redis로, (5) 읽기 복제본 — 읽기 부하 분산. 가장 흔한 hot spot: 인기 사용자, 인기 상품, 단조 증가 키. 샤드 키 선택 시 반드시 hot spot 시나리오 검토.

4. Vitess가 MySQL 분산의 표준이 된 이유는?

: (1) YouTube에서 시작 — 거대한 규모에서 검증됨, (2) MySQL 호환 — 기존 코드/도구 그대로 사용, (3) 자동 샤딩 — 키 기반 라우팅, (4) VReplication — 무중단 마이그레이션과 리샤딩, (5) CNCF 졸업 — 클라우드 네이티브 표준, (6) 검증된 사용자 — Slack, GitHub, Square. 단점은 분산 트랜잭션이 약한 편 (Saga 패턴 권장). PostgreSQL 사용자는 Citus가 유사한 역할.

5. 언제 NewSQL (CockroachDB) vs 수동 샤딩?

: NewSQL (CockroachDB, YugabyteDB) 선택: 새 프로젝트, 강한 일관성 필요 (분산 ACID), 운영 인력 부족, PostgreSQL 호환 가능. 수동 샤딩 (Vitess + MySQL) 선택: 기존 MySQL 시스템, 극단적 성능 필요, NewSQL 성숙도 우려, 더 큰 통제력 원함. 현실: 새 시스템은 점점 NewSQL로, 기존 거대 시스템은 Vitess 유지. 둘 다 valid한 선택이며 트레이드오프에 따라 결정.


참고 자료

현재 단락 (1/406)

- **샤딩 = 수평 확장의 답**: 단일 DB로 안 되는 규모에서 필수

작성 글자: 0원문 글자: 10,076작성 단락: 0/406