-
Vitess Multi Shards 구현하기 ( Sharded Keyspace )Database/Vitess 2023. 9. 6. 07:32728x90반응형
- 목차
들어가며.
Vitess 는 대규모 분산 MySQL 워크로드를 관리하기 위한 강력한 오픈 소스 데이터베이스 클러스터링 시스템입니다.
많은 트래픽과 데이터를 처리해야 하는 현대의 애플리케이션에서 데이터베이스 성능과 확장성은 매우 중요합니다.
그러나 데이터의 양이 방대해지면서 단일 데이터베이스로 이를 처리하는 데 한계가 생길 수 있습니다.
이러한 문제를 해결하기 위해 도입되는 기술 중 하나가 바로 샤딩(sharding) 입니다.
Vitess 는 동일한 Keyspace 에 여러 Shard 를 구성하고, 각 Shard 에 Vttablet 을 배치하여 데이터와 트래픽을 분산시킬 수 있습니다.
각 VTTablet 과 그 내부의 MySQL 은 샤딩된 개별적인 데이터 단위를 관리하게 됩니다.
그리고 VTGate 는 통해서 적절한 VTTablet 으로 적절한 쿼리가 라우팅되게 됩니다.
이 글에서는 Vitess 를 활용해 Multi-Shards 를 구성하는 방법을 단계별로 설명하며,
이를 통해 대규모 데이터베이스를 효과적으로 관리하는 방법을 알아보겠습니다.
Sharding 개념 이해하기.
Sharding 은 대규모 데이터베이스를 여러 개의 작은 데이터베이스(샤드) 로 나누어 데이터와 트래픽을 분산시키는 방법입니다.
Vitess 는 MySQL 데이터베이스를 자동으로 샤딩할 수 있는 기능을 제공합니다.
Vitess에서 샤딩의 주요 특징:
- 키스페이스(Keyspace): 샤딩된 데이터베이스의 논리적 그룹.
- 샤드(Shard): 키스페이스의 물리적 데이터베이스 단위.
- 분할 키(Shard Key): 데이터를 샤드 간에 분배하는 기준이 되는 키.
Sharded Keyspace 는 아래의 이미지처럼 여러 VTTablet 들로 구성됩니다.
각 VTTablet 은 Shard Key 를 기준으로 분리된 독립적인 데이터셋들을 저장합니다.
그리고 VTGate 는 Shard Key 를 기준으로 Client Query 를 분배하게 됩니다.
Vitess Sharded Keyspace 구현하기.
Vitess Multi-Shards 를 구현하기 위해서 몇가지 Vitess 구성 요소들을 생성해보도록 하겠습니다.
Etcd.
Etcd 는 Vitess Cluster 의 중앙저장소로써 동작합니다.
Etcd 는 Vitess 구성 요소, 리소스들의 상태를 저장하게 됩니다.
아래의 Docker 명령어를 통해서 Etcd Docker Container 를 실행할 수 있습니다.
docker network create vitess docker run --platform linux/amd64 -d --network vitess --name etcd \ --hostname etcd quay.io/coreos/etcd:v3.5.17 \ /usr/local/bin/etcd \ --listen-client-urls=http://0.0.0.0:2379 \ --advertise-client-urls=http://etcd:2379
아래의 명령어를 통해서 Etcd Container 내부에서 정상적인 명령어가 실행되어야 합니다.
docker exec etcd etcdctl --help
VTCtld 실행하기.
VTCtld 는 Vitess Cluster 내부에서 API Server 로써 동작합니다.
Etcd 가 Vitess Cluster 의 중앙 저장소라고 말씀드렸죠?
VTCtld 는 Etcd 로의 데이터 처리 및 조회를 도와주며, Vitess Client 의 요청을 처리합니다.
아래의 명령어를 통해서 VTCtld Container 를 실행할 수 있습니다.
docker run --platform linux/amd64 -d --network vitess --name vtctld --hostname vtctld vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctld \ --topo_implementation=etcd2 \ --topo_global_server_address=etcd:2379 \ --topo_global_root=/vitess/global \ --logtostderr=true \ --service_map="grpc-vtctlservice,grpc-vtctl,grpc-vtctld" \ --port=15000 \ --grpc_port=15999
VTCtld 컨테이너가 실행된 이후에 아래 명령어를 실행하여 VTCtld 의 정상 동작 여부를 확인할 수 있습니다.
참고로 GetCellInfoNames 는 생성된 Cell 들의 목록을 조회하는 명령어입니다.
docker exec vtctld /vt/bin/vtctldclient GetCellInfoNames --server vtctld:15999
Cell 생성하기.
Vitess 에서 Cell 은 클러스터의 논리적 영역을 나타냅니다.
아래 명령어를 실행하여 Cell을 생성합니다.
docker run --platform linux/amd64 --rm --network vitess vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient AddCellInfo --root=/vitess/global --server=vtctld:15999 --server-address=etcd:2379 zone1
docker run --platform linux/amd64 --rm --network vitess vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient AddCellInfo --root=/vitess/global --server=vtctld:15999 --server-address=etcd:2379 zone2
AddCellInfo 라는 명령어는 zone1, zone2 이라는 이름의 Cell 을 생성하며, Topology Server 인 Etcd 에 Cell 을 저장합니다.
Sharded Keyspace 생성하기.
먼저 Keyspace 를 생성합니다.
Keyspace 의 이름은 "test" 로 설정하였습니다.
아래의 명령어는 "test" Keyspace 를 생성하는 Docker 및 vtctldclient 명령어입니다.
docker run --network vitess --platform linux/amd64 --rm vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient CreateKeyspace test --server=vtctld:15999 --durability-policy=semi_sync
그리고 생성된 Keyspace 는 아래의 GetKeyspaces 명령어를 통해서 확인할 수 있습니다.
docker run --network vitess --platform linux/amd64 --rm vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient GetKeyspaces --server=vtctld:15999
이제 Keyspace 가 생성되었기 때문에 Sharded Keyspace 구성을 위해서 Shard 들을 생성해야합니다.
Shard 를 생성하기 위해서는 vtctldclient 와 CreateShard 명령어를 활용합니다.
아래의 예시는 총 4개의 Shard 를 생성하기 위한 예시입니다.
docker run --network vitess --platform linux/amd64 --rm vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient CreateShard --server=vtctld:15999 test/-40 docker run --network vitess --platform linux/amd64 --rm vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient CreateShard --server=vtctld:15999 test/40-80 docker run --network vitess --platform linux/amd64 --rm vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient CreateShard --server=vtctld:15999 test/80-cc docker run --network vitess --platform linux/amd64 --rm vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient CreateShard --server=vtctld:15999 test/cc-
그리고 생성된 Keyspace 와 Shard 들은 FindAllShardsInKeyspace 명령어를 통해서 확인할 수 있습니다.
docker run --network vitess --platform linux/amd64 --rm vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient FindAllShardsInKeyspace --server=vtctld:15999 test
{ "shards":{ "-40":{"keyspace":"test","name":"-40","shard":{"primary_alias":null,"primary_term_start_time":null,"key_range":{"start":"","end":"QA=="},"source_shards":[],"tablet_controls":[],"is_primary_serving":true}}, "40-80":{"keyspace":"test","name":"40-80","shard":{"primary_alias":null,"primary_term_start_time":null,"key_range":{"start":"QA==","end":"gA=="},"source_shards":[],"tablet_controls":[],"is_primary_serving":true}}, "80-CC":{"keyspace":"test","name":"80-CC","shard":{"primary_alias":null,"primary_term_start_time":null,"key_range":{"start":"gA==","end":"zA=="},"source_shards":[],"tablet_controls":[],"is_primary_serving":true}}, "CC-":{"keyspace":"test","name":"CC-","shard":{"primary_alias":null,"primary_term_start_time":null,"key_range":{"start":"zA==","end":""},"source_shards":[],"tablet_controls":[],"is_primary_serving":true}} } }
위 과정들은 통해서 Sharded Keyspace 구성이 완료되었습니다.
VTTablet 구성하기.
생성된 Shard 와 매칭할 VTTablet 들을 생성합니다.
"test" Keyspace 는 총 4개의 Shard 로 구성되었고, 각 Shard 를 담당하는 4개의 VTTablet 을 생성해보려고 합니다.
Tablet Uid 를 0000000002, 0000000003, 0000000004 로 변경하고,
Shard 의 범위를 -40, 40-80, 80-CC, CC- 로 변경하며 4개의 VTTablet 을 생성합니다.
create_vttablet_container() { local CELL=$1 local TABLET_UID=$2 local SHARD=$3 local HOST_PORT=$4 local TABLET_UID_WITH_PADDING=$(printf "%010d" $TABLET_UID) docker run --network vitess --platform linux/amd64 -d \ --name vttablet-${CELL}-${TABLET_UID_WITH_PADDING} --hostname vttablet-${CELL}-${TABLET_UID_WITH_PADDING} \ --env CELL=${CELL} --env TABLET_UID=${TABLET_UID} -e SHARD=${SHARD} --env TABLET_UID_WITH_PADDING=${TABLET_UID_WITH_PADDING} \ -p ${HOST_PORT}:15000 \ vitess/lite:v17.0.7-mysql80 \ bash -c '\ /vt/bin/mysqlctld \ --tablet_uid=${TABLET_UID} \ --db_charset=utf8mb4 \ --db_dba_user=root \ --logtostderr=true \ --mysql_socket=/vt/vtdataroot/vt_${TABLET_UID_WITH_PADDING}/mysql.sock \ --socket_file=/vt/vtdataroot/vt_${TABLET_UID_WITH_PADDING}/mysqlctl.sock \ & sleep 15; \ /vt/bin/vttablet \ --db_charset=utf8mb4 \ --grpc_port=15999 \ --init_keyspace=test \ --init_shard=${SHARD} \ --init_tablet_type=replica \ --mysqlctl_socket=/vt/vtdataroot/vt_${TABLET_UID_WITH_PADDING}/mysqlctl.sock \ --port=15000 \ --topo_implementation=etcd2 \ --topo_global_server_address=etcd:2379 \ --topo_global_root=/vitess/global \ --logtostderr=true \ --tablet-path=${CELL}-${TABLET_UID_WITH_PADDING} \ --service_map=grpc-queryservice,grpc-tabletmanager,grpc-updatestream' }
create_vttablet_container zone1 1 "-40" 15001 create_vttablet_container zone1 2 "40-80" 15002 create_vttablet_container zone1 3 "80-cc" 15003 create_vttablet_container zone1 4 "cc-" 15004 create_vttablet_container zone2 5 "-40" 15005 create_vttablet_container zone2 6 "40-80" 15006 create_vttablet_container zone2 7 "80-cc" 15007 create_vttablet_container zone2 8 "cc-" 15008
아래의 이미지들처럼 4개의 VTTablet 이 Replica & Not Serving 상태로 준비되어 있습니다.
PlannedReparentShard.
이제 각 VTTablet 을 Primary 상태로 변경해야합니다.
Replica Tablet 을 Primary Tablet 으로 변경하기 위한 PlannedReparentShard 명령어 예시는 아래와 같습니다.
docker run --platform linux/amd64 --rm --network vitess vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient PlannedReparentShard --server=vtctld:15999 test/-40 --new-primary=zone1-0000000001 docker run --platform linux/amd64 --rm --network vitess vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient PlannedReparentShard --server=vtctld:15999 test/40-80 --new-primary=zone1-0000000002 docker run --platform linux/amd64 --rm --network vitess vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient PlannedReparentShard --server=vtctld:15999 test/80-cc --new-primary=zone1-0000000003 docker run --platform linux/amd64 --rm --network vitess vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient PlannedReparentShard --server=vtctld:15999 test/cc- --new-primary=zone1-0000000004
위의 PlannedReparentShard 명령어를 통해서 Replica Tablet 들을 Primary Tablet 으로 승격시킬 수 있습니다.
아래의 이미지처럼 Primary 타입으로 변경됨을 확인할 수 있습니다.
VTGate 실행하기.
이제 VTGate 를 Vitess Cluster 내에 추가하여 클라이언트의 요청 쿼리를 실행시켜볼 것입니다.
총 4개의 VTTablet 이 존재하며 요청 쿼리는 적절한 VTTablet 에 분배될 예정입니다.
아래의 링크는 Vitess 의 VTGate 를 실행시킬 수 있는 가이드를 작성한 내용을 포함합니다.
https://westlife0615.tistory.com/402
위 링크의 내용에서 사용되는 Script 들만 가려내서 아래의 명령어 목록을 나열해보았습니다.
cat <<'EOF'> /tmp/users.json { "default": [{ "UserData": "default", "MysqlNativePassword": "A4B6157319038724E3560894F7F932C8886EBFCF" }] } EOF
docker run --network vitess --platform linux/amd64 -d \ --name vtgate --hostname vtgate \ --mount type=bind,source=/tmp/users.json,target=/vt/users.json \ -p 3307:3306 \ -p 15990:15999 \ -p 15010:15000 \ vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtgate \ --logtostderr=true \ --topo_global_root=/vitess/global \ --topo_global_server_address=etcd:2379 \ --topo_implementation=etcd2 \ --tablet_types_to_wait=PRIMARY,REPLICA \ --cell=zone1 \ --cells_to_watch=zone1,zone1 \ --grpc_port=15999 \ --port=15000 \ --mysql_server_port=3306 \ --mysql_server_version=8.0.30 \ --mysql_auth_server_impl=static \ --mysql_auth_server_static_file=/vt/users.json
그리고 VTGate 가 정상적으로 실행된다면 아래의 Web UI 결과를 확인할 수 있습니다.
데이터 생성하기.
Sharded Keyspace 에서 사용할 MySQL Table 을 생성하고 데이터를 추가하는 테스트를 진행해보도록 하겠습니다.
먼저 Table 을 생성합니다.
Sharded Keyspace 는 여러개의 MySQL 로 구성되어 있기 때문에 vtctldclient 명령어를 통해서 테이블을 생성할 수 있습니다.
이 명령어는 test Keyspace의 모든 샤드에 동일한 테이블을 생성합니다.
docker run --platform linux/amd64 --rm --network vitess vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient ApplySchema --server=vtctld:15999 --sql="CREATE TABLE customer ( customer_id BIGINT NOT NULL, name VARCHAR(255), email VARCHAR(255), PRIMARY KEY (customer_id) )" test
아래의 명령어를 실행해서 모든 VTTablet 의 MySQL 내부에 customer 테이블이 생성됨을 확인할 수 있습니다.
docker exec vttablet-zone1-0000000001 mysql \ -S /vt/vtdataroot/vt_0000000001/mysql.sock \ -u vt_dba \ -e "USE vt_test; show create table customer;";
그리고 ApplyVSchema 명령어를 통해서 VTGate 에서 사용할 Sharding Key 를 지정합니다.
아래의 ApplyVSchema 명령어를 통해서 VTGate 에게 전달되는 모든 쿼리들은 적절한 VTGate 로 라우팅될 수 있습니다.
docker run --platform linux/amd64 --rm --network vitess vitess/lite:v17.0.7-mysql80 \ /vt/bin/vtctldclient ApplyVSchema --server=vtctld:15999 --vschema='{ "sharded": true, "vindexes": { "hash": { "type": "hash" } }, "tables": { "customer": { "column_vindexes": [ { "column": "customer_id", "name": "hash" } ] } } }' test
쿼리 실행해보기.
VTGate 와 연결된 MySQL Shell 을 통해서 아래의 쿼리를 실행합니다.
INSERT INTO customer (customer_id, name, email) VALUES (1, 'Alice Johnson', 'alice.johnson@example.com');
위 쿼리가 실행되면, 첫번째 Shard 인 zone1-0000000001 Tablet 내부에 데이터가 생성되구요.
zone1-0000000001 의 Replica 인 zone2-0000000005 Tablet 내부에서도 데이터가 확인됩니다.
docker exec vttablet-zone1-0000000001 mysql -S /vt/vtdataroot/vt_0000000001/mysql.sock -u vt_dba -e "select * from vt_test.customer"; docker exec vttablet-zone1-0000000002 mysql -S /vt/vtdataroot/vt_0000000002/mysql.sock -u vt_dba -e "select * from vt_test.customer"; docker exec vttablet-zone1-0000000003 mysql -S /vt/vtdataroot/vt_0000000003/mysql.sock -u vt_dba -e "select * from vt_test.customer"; docker exec vttablet-zone1-0000000004 mysql -S /vt/vtdataroot/vt_0000000004/mysql.sock -u vt_dba -e "select * from vt_test.customer"; docker exec vttablet-zone2-0000000005 mysql -S /vt/vtdataroot/vt_0000000005/mysql.sock -u vt_dba -e "select * from vt_test.customer"; docker exec vttablet-zone2-0000000006 mysql -S /vt/vtdataroot/vt_0000000006/mysql.sock -u vt_dba -e "select * from vt_test.customer"; docker exec vttablet-zone2-0000000007 mysql -S /vt/vtdataroot/vt_0000000007/mysql.sock -u vt_dba -e "select * from vt_test.customer"; docker exec vttablet-zone2-0000000008 mysql -S /vt/vtdataroot/vt_0000000008/mysql.sock -u vt_dba -e "select * from vt_test.customer";
반응형'Database > Vitess' 카테고리의 다른 글
[Vitess] VTOrc Orchestration 알아보기 ( EmergencyReparentShard ) (0) 2023.10.30 [Vitess] Docker 환경에서 vttablet 실행하기: 단계별 가이드 (0) 2023.09.19 KinD 로 Vitess 구현하기. (0) 2023.09.05 [Vitess] Vitess 환경에서 Primary-Replica Replication 구축하기 (0) 2023.04.10 [Vitess] mysqlctld 기본적인 사용법 알아보기 (0) 2023.01.31