1. 수직 샤딩이란?
수직 샤딩(Vertical Sharding)은 특정 테이블을 별도의 MySQL 서버에서 관리하는 방식입니다. 예를 들어, 하나의 데이터베이스에 product, corder, customer 테이블이 있다면, corder, customer 테이블만 다른 MySQL 서버로 옮기는 것이 수직 샤딩입니다.
Vitess에서는 MoveTables 기능을 활용하여 특정 테이블을 다른 키스페이스(Keyspace)로 이동할 수 있습니다.
classDiagram
class Commerce {
product
}
class Customer {
corder
customer
}
class BeforeSharding {
product
corder
customer
}
BeforeSharding --> Commerce : Retain product
BeforeSharding --> Customer : Move corder, customer
2. MoveTables 개요
MoveTables는 서버를 다운시키지 않고 키스페이스 간 특정 테이블을 이동하는 워크플로우입니다.
주요 특징
- 초기 Vitess 배포 후 단일 스키마가 커질 경우 여러 키스페이스로 분할하는 데 사용됨
- 이를 "수직 샤딩(Vertical Sharding)"이라고 함
- 샤드를 줄이면 데이터가 다른 샤드로 이동한 후 샤드를 제거하는 방식
- 데이터는 안전하게 이동됨
예제 실행: 키스페이스 및 MySQL 인스턴스 생성
# 더미 데이터 삽입
mysql < ../common/insert_commerce_data.sql
# 삽입된 데이터 보기
mysql --table < ../common/select_commerce_data.sql
# 새로운 클러스터 실행
./201_customer_tablets.sh
이 스크립트를 실행하면 customer 키스페이스가 생성되고 MySQL 인스턴스 3개가 가동됩니다.
참고: vttablet 실행 시 키스페이스를 생성하지 않았다면 자동으로 생성됩니다.
commerce 키스페이스 테이블에 데이터 삽입
[vitess@rocky-linux-8 local]$ mysql < ../common/insert_commerce_data.sql
[vitess@rocky-linux-8 local]$ mysql --table < ../common/select_commerce_data.sql
Using commerce
Customer
+-------------+--------------------+
| customer_id | email |
+-------------+--------------------+
| 1 | alice@domain.com |
| 2 | bob@domain.com |
| 3 | charlie@domain.com |
| 4 | dan@domain.com |
| 5 | eve@domain.com |
+-------------+--------------------+
Product
+----------+-------------+-------+
| sku | description | price |
+----------+-------------+-------+
| SKU-1001 | Monitor | 100 |
| SKU-1002 | Keyboard | 30 |
+----------+-------------+-------+
COrder
+----------+-------------+----------+-------+
| order_id | customer_id | sku | price |
+----------+-------------+----------+-------+
| 1 | 1 | SKU-1001 | 100 |
| 2 | 2 | SKU-1002 | 30 |
| 3 | 3 | SKU-1002 | 30 |
| 4 | 4 | SKU-1002 | 30 |
| 5 | 5 | SKU-1002 | 30 |
+----------+-------------+----------+-------+
mysql 인스턴스도 총 6개 실행중인걸 확인 할 수 있다
[vitess@rocky-linux-8 local]$ ps -ef |grep mysql
vitess 24278 1 1 15:14 pts/0 00:03:52 /usr/sbin/mysqld --defaults-file=/var/lib/vitess/vtdataroot/vt_0000000102/my.cnf --basedir=/usr
vitess 24297 1 1 15:14 pts/0 00:03:35 /usr/sbin/mysqld --defaults-file=/var/lib/vitess/vtdataroot/vt_0000000101/my.cnf --basedir=/usr
vitess 24300 1 1 15:14 pts/0 00:03:41 /usr/sbin/mysqld --defaults-file=/var/lib/vitess/vtdataroot/vt_0000000100/my.cnf --basedir=/usr
vitess 27982 1 0 15:18 pts/0 00:00:33 vtgate --config-file-not-found-handling=ignore --topo_implementation etcd2 --topo_global_server_address localhost:2379 --topo_global_root /vitess/global --log_dir /var/lib/vitess/vtdataroot/tmp --log_queries_to_file /var/lib/vitess/vtdataroot/tmp/vtgate_querylog.txt --port 15001 --grpc_port 15991 --mysql_server_port 15306 -mysql_server_socket_path /tmp/mysql.sock --cell zone1 --cells_to_watch zone1 --tablet_types_to_wait PRIMARY,REPLICA --service_map grpc-vtgateservice --pid_file /var/lib/vitess/vtdataroot/tmp/vtgate.pid --enable_buffer --mysql_auth_server_impl none --pprof-http
vitess 35585 1 3 20:21 pts/0 00:00:02 /usr/sbin/mysqld --defaults-file=/var/lib/vitess/vtdataroot/vt_0000000200/my.cnf --basedir=/usr
vitess 35719 1 3 20:22 pts/0 00:00:02 /usr/sbin/mysqld --defaults-file=/var/lib/vitess/vtdataroot/vt_0000000201/my.cnf --basedir=/usr
vitess 35847 1 11 20:22 pts/0 00:00:07 /usr/sbin/mysqld --defaults-file=/var/lib/vitess/vtdataroot/vt_0000000202/my.cnf --basedir=/usr
vitess 36135 2695 0 20:23 pts/0 00:00:00 grep --color=auto mysql
customer 키스페이스에는 테이블이 없는 걸 확인 할 수 있다.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| commerce |
| customer |
| information_schema |
| mysql |
| sys |
| performance_schema |
+--------------------+
6 rows in set (0.00 sec)
mysql> use customer
Database changed
mysql> show tables;
Empty set (0.00 sec)
3. MoveTables 사용법
3.1 키스페이스 정보 확인
mysql -e "show vitess_tablets"
출력 예시:
[vitess@rocky-linux-8 local]$ mysql -e "show vitess_tablets"
+-------+----------+-------+------------+---------+------------------+---------------+----------------------+
| Cell | Keyspace | Shard | TabletType | State | Alias | Hostname | PrimaryTermStartTime |
+-------+----------+-------+------------+---------+------------------+---------------+----------------------+
| zone1 | commerce | 0 | PRIMARY | SERVING | zone1-0000000100 | rocky-linux-8 | 2025-03-07T06:14:45Z |
| zone1 | commerce | 0 | REPLICA | SERVING | zone1-0000000101 | rocky-linux-8 | |
| zone1 | commerce | 0 | RDONLY | SERVING | zone1-0000000102 | rocky-linux-8 | |
| zone1 | customer | 0 | PRIMARY | SERVING | zone1-0000000201 | rocky-linux-8 | 2025-03-07T11:22:37Z |
| zone1 | customer | 0 | REPLICA | SERVING | zone1-0000000200 | rocky-linux-8 | |
| zone1 | customer | 0 | RDONLY | SERVING | zone1-0000000202 | rocky-linux-8 | |
+-------+----------+-------+------------+---------+------------------+---------------+----------------------+
- PRIMARY, REPLICA, RDONLY 각각 다른 서버에 존재 가능
- REPLICA, RDONLY는 PRIMARY를 참조하여 데이터 동기화(복제)
- PRIMARY가 죽으면 REPLICA를 PRIMARY로 승격 가능
3.2 MoveTables 실행 (create)
# ./202_move_tables.sh
vtctldclient MoveTables --workflow commerce2customer \\
--target-keyspace customer \\
create --source-keyspace commerce \\
--tables "customer,corder"
- customer 키스페이스에 customer, corder 테이블이 생성되고 데이터가 복제됨
- 그러나 아직 트래픽 전환 전 상태이며 commerce 키스페이스가 원본으로 유지됨
테이블이 없었던 customer 키스페이스에 corder, customer 테이블이 복제된 걸 확인 할 수 있다.
mysql> show tables;
+--------------------+
| Tables_in_customer |
+--------------------+
| corder |
| customer |
+--------------------+
2 rows in set (0.01 sec)
mysql> select * from corder;
+----------+-------------+----------+-------+
| order_id | customer_id | sku | price |
+----------+-------------+----------+-------+
| 1 | 1 | SKU-1001 | 100 |
| 2 | 2 | SKU-1002 | 30 |
| 3 | 3 | SKU-1002 | 30 |
| 4 | 4 | SKU-1002 | 30 |
| 5 | 5 | SKU-1002 | 30 |
+----------+-------------+----------+-------+
5 rows in set (0.00 sec)
mysql> select * from customer;
+-------------+--------------------+
| customer_id | email |
+-------------+--------------------+
| 1 | alice@domain.com |
| 2 | bob@domain.com |
| 3 | charlie@domain.com |
| 4 | dan@domain.com |
| 5 | eve@domain.com |
+-------------+--------------------+
5 rows in set (0.00 sec)
# 만약에 commerce 키스페이스의 customer 테이블에 데이터가 삽입 되면 어떻게 될까?
mysql> use commerce;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+--------------------+
| Tables_in_commerce |
+--------------------+
| corder |
| customer |
| product |
+--------------------+
3 rows in set (0.00 sec)
mysql> select * from customer;
+-------------+--------------------+
| customer_id | email |
+-------------+--------------------+
| 1 | alice@domain.com |
| 2 | bob@domain.com |
| 3 | charlie@domain.com |
| 4 | dan@domain.com |
| 5 | eve@domain.com |
+-------------+--------------------+
5 rows in set (0.01 sec)
mysql> insert into customer values(6, 'wowls5000@cowave.kr');
Query OK, 1 row affected (0.02 sec)
# customer 키스페이스의 customer 테이블에 데이터가 동기화 된 걸 확인 할 수 있다.
mysql> select * from customer.customer;
+-------------+---------------------+
| customer_id | email |
+-------------+---------------------+
| 1 | alice@domain.com |
| 2 | bob@domain.com |
| 3 | charlie@domain.com |
| 4 | dan@domain.com |
| 5 | eve@domain.com |
| 6 | wowls5000@cowave.kr |
+-------------+---------------------+
6 rows in set (0.01 sec)
트래픽 전환 여부 확인:
vtctldclient GetRoutingRules
출력 예시:
"from_table": "customer.customer" -> "to_tables": ["commerce.customer"]
- 이는 customer 키스페이스의 customer 테이블이 실제 commerce 키스페이스를 참조하고 있음을 의미함
commerce.customer에 데이터를 삽입하면 customer.customer에 자동 반영됨
3.3 데이터 동기화 확인
vtctldclient VDiff --target-keyspace customer --workflow commerce2customer create
vtctldclient VDiff --format=json --target-keyspace customer --workflow commerce2customer show last --verbose
이 명령어를 사용하면 소스 키스페이스와 타겟 키스페이스 간 데이터 동기화 여부를 확인할 수 있습니다.
3.4 미러링 설정 (선택 사항)
vtctldclient MoveTables --target-keyspace customer --workflow commerce2customer MirrorTraffic --percent 1.0
- 실시간 트래픽을 복사하여 마이그레이션 테스트 및 안정성 검증
- 트래픽 스위칭 전 반드시 테스트하는 것이 권장됨
4. 트래픽 전환
rdonly,replica, primary 모두 commerce 키스페이스에서 customer 키스페이스로 트래픽을 전환해야 마이그레이션을 완료 할 수 있다.
데이터 유실 방지를 위해 미러링 활성화 후 트래픽을 전환하는 것이 좋음
# 203_switch_reads.sh
vtctldclient MoveTables --workflow commerce2customer --target-keyspace customer switchtraffic --tablet-types "rdonly,replica"
# 204_switch_writes.sh
vtctldclient MoveTables --workflow commerce2customer --target-keyspace customer switchtraffic --tablet-types primary
- rdonly, replica 먼저 전환 후 primary 전환
- 전환 후 리버스 워크플로우(customer2commerce_reverse) 생성됨
5. 트래픽 되돌리기 및 작업 취소
되돌리기:
vtctldclient MoveTables --workflow customer2commerce --target-keyspace commerce reversetraffic
완전 취소:
vtctldclient MoveTables --workflow customer2commerce --target-keyspace commerce cancel
6. 최종 완료 (워크플로우 삭제)
# 205_clean_commerce.sh
vtctldclient MoveTables --target-keyspace customer --workflow commerce2customer complete
- 이 명령을 실행하면 워크플로우가 삭제되고 최종 마이그레이션 완료됨
complete 전 상태
mysql> show tables;
+--------------------+
| Tables_in_commerce |
+--------------------+
| corder |
| customer |
| product |
+--------------------+
3 rows in set (0.01 sec)
mysql> show tables;
+--------------------+
| Tables_in_customer |
+--------------------+
| corder |
| customer |
+--------------------+
2 rows in set (0.00 sec)
complete 후 최종 상태
mysql> show tables;
+--------------------+
| Tables_in_commerce |
+--------------------+
| product |
+--------------------+
1 row in set (0.01 sec)
mysql> show tables;
+--------------------+
| Tables_in_customer |
+--------------------+
| corder |
| customer |
+--------------------+
2 rows in set (0.00 sec)
7. 정리
- 수직 샤딩을 통해 특정 테이블을 다른 MySQL 서버로 분리 가능
- MoveTables 기능을 사용하여 서버 중단 없이 테이블 이동
- 트래픽 전환 전 반드시 데이터 동기화 확인 (VDiff 사용)
- 미러링 트래픽 테스트를 통해 안정성 검증
- 트래픽 전환 완료 후 리버스 워크플로우 관리
- 작업이 끝나면 complete 실행하여 최종 정리
- MoveTables 작업을 Complete 단계까지 완료하려면 PRIMARY(기본), REPLICA(복제본), RDONLY(읽기 전용) 모든 트래픽을 새로운 대상(타겟)으로 전환해야 합니다.
'기술, 개발 > Vitess' 카테고리의 다른 글
| Vitess 수평샤딩 2 (리샤딩) (2) | 2025.08.28 |
|---|---|
| Vitess 수평 샤딩 1 (시퀀스) (0) | 2025.08.28 |
| vtctld, vtgate, vttablet, vtorc (0) | 2025.08.28 |
| Vitess 기본 개념 (0) | 2025.08.28 |
| 로키리눅스 vitess 설치 (0) | 2025.08.28 |