Vitess: YouTube가 설계한 MySQL 수평 샤딩 아키텍처와 프로덕션 운영 기준
요약
MySQL은 단일 서버에서 탁월하지만, 데이터가 수 TB를 넘고 초당 수십만 건의 쿼리를 처리해야 하는 시점에 한계가 온다. Vitess는 YouTube가 2010년 이 문제를 풀기 위해 만든 MySQL 수평 샤딩 레이어로, 2019년 CNCF Graduated 프로젝트가 됐다. GitHub, Slack, PlanetScale이 이 위에서 수억 건의 트랜잭션을 처리한다.
| 기능 | Vitess | MySQL 단독 |
|---|---|---|
| 수평 확장 | 무제한 샤딩 | 불가 |
| 연결 풀링 | VTTablet 내장 | 외부 도구 필요 |
| 온라인 DDL | 내장 지원 | pt-osc/gh-ost 필요 |
| 쿼리 라우팅 | 자동 | 수동 |
| 샤드 추가 | 다운타임 없음 | 다운타임 필요 |
MySQL 수평 스케일링의 문제
MySQL의 수직 확장(CPU, RAM, SSD 추가)은 한계가 있다. 단일 Primary가 처리할 수 있는 쓰기 처리량, 연결 수, 저장 용량에 물리적 상한이 존재한다.
수평 확장의 기존 방법들은 저마다 문제가 있었다.
- 수동 샤딩: 애플리케이션 코드가 샤딩 로직을 알아야 하고, 리샤딩 시 다운타임 불가피
- 읽기 복제본(Read Replica): 쓰기 병목 해결 불가
- 갤러리 클러스터: 쓰기 충돌과 성능 저하 문제
- NoSQL 전환: 트랜잭션, 조인, ACID 포기
Vitess는 애플리케이션에는 단일 MySQL처럼 보이면서, 내부적으로 여러 MySQL 인스턴스에 데이터와 쿼리를 분산한다.
아키텍처 구성요소
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개 샤드로 나눌 수 있다.
단계별 과정
- 소스 샤드 특정: 분할할 샤드 선택 (예: 샤드 0을 샤드 00과 01로)
- 타깃 샤드 생성: 빈 MySQL + VTTablet 인스턴스 준비
- VReplication 시작: 소스에서 타깃으로 스트리밍 복제 시작
- 쓰기 따라잡기(Catch-up): 타깃이 소스의 지연(lag)을 0에 가깝게 줄임
- 트래픽 전환: VTGate가 라우팅을 새 샤드로 전환
- 소스 샤드 정리: 일정 기간 후 소스 데이터 삭제
이 전 과정에서 애플리케이션은 다운타임 없이 계속 운영된다.
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 대안 비교
| 항목 | Vitess | ProxySQL | CockroachDB |
|---|---|---|---|
| 프로토콜 | MySQL | MySQL | PostgreSQL |
| 수평 샤딩 | 완전 지원 | 없음 | 내장 (분산 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