LLM WikiAccess-protected knowledge portal
← 스터디 홈
156편 · 약 15분

Vitess: YouTube가 설계한 MySQL 수평 샤딩 아키텍처와 프로덕션 운영 기준

요약

MySQL은 단일 서버에서 탁월하지만, 데이터가 수 TB를 넘고 초당 수십만 건의 쿼리를 처리해야 하는 시점에 한계가 온다. Vitess는 YouTube가 2010년 이 문제를 풀기 위해 만든 MySQL 수평 샤딩 레이어로, 2019년 CNCF Graduated 프로젝트가 됐다. GitHub, Slack, PlanetScale이 이 위에서 수억 건의 트랜잭션을 처리한다.

기능VitessMySQL 단독
수평 확장무제한 샤딩불가
연결 풀링VTTablet 내장외부 도구 필요
온라인 DDL내장 지원pt-osc/gh-ost 필요
쿼리 라우팅자동수동
샤드 추가다운타임 없음다운타임 필요

MySQL 수평 스케일링의 문제

MySQL의 수직 확장(CPU, RAM, SSD 추가)은 한계가 있다. 단일 Primary가 처리할 수 있는 쓰기 처리량, 연결 수, 저장 용량에 물리적 상한이 존재한다.

수평 확장의 기존 방법들은 저마다 문제가 있었다.

  • 수동 샤딩: 애플리케이션 코드가 샤딩 로직을 알아야 하고, 리샤딩 시 다운타임 불가피
  • 읽기 복제본(Read Replica): 쓰기 병목 해결 불가
  • 갤러리 클러스터: 쓰기 충돌과 성능 저하 문제
  • NoSQL 전환: 트랜잭션, 조인, ACID 포기

Vitess는 애플리케이션에는 단일 MySQL처럼 보이면서, 내부적으로 여러 MySQL 인스턴스에 데이터와 쿼리를 분산한다.


아키텍처 구성요소

Vitess 클러스터 아키텍처 애플리케이션 (MySQL 프로토콜로 연결) 기존 MySQL 드라이버 그대로 사용 — Vitess 존재를 알 필요 없음 VTGate (stateless 쿼리 라우터) MySQL 프로토콜 수신 → VSchema 참조 → 대상 샤드 결정 → VTTablet 전달 여러 인스턴스로 수평 확장 가능 (L4 로드밸런서 앞에 배치) 토폴로지 서비스 etcd / ZooKeeper 샤드 0 (키 0x00-0x7f) VTTablet (Primary) 연결 풀링, 쿼리 실행 VTTablet (Replica) 읽기 부하 분산 MySQL 8.x 샤드 1 (키 0x80-0xff) VTTablet (Primary) 연결 풀링, 쿼리 실행 VTTablet (Replica) 읽기 부하 분산 MySQL 8.x 비샤딩 키스페이스 (users, config 등 소형 테이블) VTTablet (Primary) 단일 MySQL 인스턴스 MySQL 8.x 메타데이터
Vitess 클러스터 아키텍처

VTGate

  • 역할: 클라이언트가 MySQL 프로토콜로 연결하는 stateless 프록시 라우터
  • 들어오는 SQL을 파싱하고, VSchema를 참조해 어느 샤드로 보낼지 결정
  • 교차-샤드 쿼리(scatter gather)는 여러 샤드에 분산 실행 후 결과 합산
  • Stateless이므로 L4 로드밸런서 뒤에 다수 인스턴스를 배치해 수평 확장 가능

VTTablet

  • 역할: 각 MySQL 인스턴스 옆에 배치되는 사이드카 프록시
  • VTGate와 MySQL 사이에서 연결 풀링을 담당 (MySQL max_connections 보호)
  • 쿼리 실행 전 BEGIN, SET 등의 불필요한 호출을 최소화
  • 복제 지연 모니터링 및 타블렛 상태 관리
  • 한 MySQL 인스턴스에 Primary VTTablet과 Replica VTTablet이 각각 연결

토폴로지 서비스

  • etcd 또는 ZooKeeper에 클러스터 메타데이터 저장 (키스페이스 정의, 샤드 목록, 타블렛 위치)
  • 쿼리 핫패스에는 사용되지 않음 — VTGate가 캐시 유지
  • 주기적으로 또는 변경 시에만 접근

VSchema: 샤딩 규칙 정의

VSchema는 Vitess가 쿼리를 라우팅하는 데 사용하는 가상 스키마다. JSON으로 정의하며, 각 테이블의 샤딩 방식을 기술한다.

키스페이스(Keyspace)

하나의 논리적 데이터베이스 단위다. 샤딩 키스페이스비샤딩 키스페이스로 나뉜다.

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

Vindex (가상 인덱스)

Vindex는 테이블의 컬럼 값을 keyspace ID(64비트 정수)로 변환하는 함수다. 이 keyspace ID가 어느 샤드로 갈지를 결정한다.

Vindex 타입동작사용 사례
hash컬럼 값의 해시 → keyspace ID균일 분산, 단순 PK
binary이진 값 직접 사용UUID, 범위 쿼리
numeric숫자를 keyspace ID로숫자형 PK
lookup별도 룩업 테이블 참조비PK 컬럼 검색

샤딩 키 선택 기준:

  • 데이터가 균일하게 분산되어야 함 (핫샤드 방지)
  • 대부분의 쿼리가 단일 샤드에서 처리되어야 함 (교차-샤드 쿼리 최소화)
  • 변경 불가능한 값이어야 함 (user_id, order_id 등)

리샤딩: 다운타임 없는 샤드 분할

데이터가 증가해 현재 2개 샤드로 부족해지면, VReplication 기반의 리샤딩으로 4개 샤드로 나눌 수 있다.

단계별 과정

  1. 소스 샤드 특정: 분할할 샤드 선택 (예: 샤드 0을 샤드 00과 01로)
  2. 타깃 샤드 생성: 빈 MySQL + VTTablet 인스턴스 준비
  3. VReplication 시작: 소스에서 타깃으로 스트리밍 복제 시작
  4. 쓰기 따라잡기(Catch-up): 타깃이 소스의 지연(lag)을 0에 가깝게 줄임
  5. 트래픽 전환: VTGate가 라우팅을 새 샤드로 전환
  6. 소스 샤드 정리: 일정 기간 후 소스 데이터 삭제

이 전 과정에서 애플리케이션은 다운타임 없이 계속 운영된다.


Online DDL: 스키마 변경의 안전망

Vitess의 Online DDL은 ALTER TABLE 같은 스키마 변경을 무중단으로 처리한다.

-- Vitess를 통한 Online DDL
ALTER TABLE orders ADD COLUMN coupon_code VARCHAR(50);

내부적으로 gh-ost 또는 pt-osc와 유사한 방식으로 동작하지만, Vitess가 직접 관리하므로 복제 지연, 트래픽 급등 시 자동 throttle 기능이 포함돼 있다.

-- DDL 진행 상황 확인
SHOW VITESS_MIGRATIONS LIKE 'orders';

-- 중단/재개
ALTER VITESS_MIGRATION '<uuid>' CANCEL;
ALTER VITESS_MIGRATION '<uuid>' RETRY;

연결 풀링과 connection storm 방지

MySQL의 max_connections는 수천 개 이상으로 올리기 어렵다. 애플리케이션 인스턴스가 수백 개가 되면 연결 수 초과(connection storm)가 발생한다.

VTTablet 연결 풀링 구조:

  • 각 VTTablet은 MySQL에 대해 제한된 내부 연결 풀 유지 (기본 OLTP: 300~500)
  • 애플리케이션은 VTTablet에 수천 개 연결 가능 (가상 연결)
  • 트랜잭션이 없을 때는 연결을 풀에 반환
항목직접 연결Vitess VTTablet
MySQL에 대한 실제 연결 수앱 인스턴스 × 풀 크기VTTablet 풀 크기 (300~500)
연결 관리앱이 직접 관리Vitess 자동 관리
Connection storm 위험높음낮음

운영 체크리스트

초기 설정

  • [ ] 샤딩 키 결정: 핫샤드 방지를 위해 cardinality 높은 컬럼 선택
  • [ ] 비샤딩 테이블 분리: 작은 참조 테이블은 unsharded keyspace에 배치
  • [ ] VTTablet pool_size 설정: MySQL max_connections의 30~40% 수준
  • [ ] 교차-샤드 쿼리 금지 목록 작성: scatter gather는 비용이 크다

모니터링

  • [ ] VTTablet QPS, Latency, ErrorRate 지표 수집
  • [ ] tablet_errors_total — MySQL 오류 분류별 추적
  • [ ] 복제 지연: replication_lag_seconds > 10초 시 알림
  • [ ] VReplication 진행률: 리샤딩 중 vreplication 테이블 모니터링

리샤딩 전 확인

  • [ ] 교차-샤드 트랜잭션 없음 확인
  • [ ] 스테이징 환경에서 리샤딩 리허설 실행
  • [ ] 트래픽 전환 롤백 절차 준비
  • [ ] 소스 샤드 데이터 최소 72시간 보관 후 삭제

Vitess vs 대안 비교

항목VitessProxySQLCockroachDB
프로토콜MySQLMySQLPostgreSQL
수평 샤딩완전 지원없음내장 (분산 SQL)
기존 MySQL 호환높음높음낮음 (SQL 방언 차이)
운영 복잡도높음낮음중간
사용 규모극대형대형대형

References

  • https://vitess.io/docs/24.0/reference/features/sharding/ (Vitess 공식 샤딩 문서)
  • https://planetscale.com/learn/courses/vitess/components-of-a-vitess-cluster (PlanetScale Vitess 구성 요소 강좌)
  • https://vitess.io/docs/24.0/reference/features/schema-changes/ (Vitess Online DDL)
  • https://oneuptime.com/blog/post/2026-03-31-mysql-how-to-use-vitess-for-mysql-horizontal-scaling/view
  • https://oneuptime.com/blog/post/2026-02-09-vitess-sharded-mysql-kubernetes/view
  • https://andrewjdawson2016.medium.com/understanding-the-architecture-of-vitess-5f3c042c4cdd