Vitess — слой шардирования и маршрутизации поверх MySQL, который позволяет приложению работать с одним логическим кластером, пока данные разложены по шардам. Он не заменяет MySQL, а управляет соединениями, репликацией, схемами и переездами без остановки сервиса. Ниже — путь от локального стенда до VSchema и онлайн-перешардирования.
Когда MySQL нужен шардинг, а когда — нет
Сначала исчерпайте простые варианты: индексы, партиционирование, реплики для чтения, кэш и разделение сервисов по базам. Шардинг усложняет транзакции, JOIN и резервное копирование. Vitess оправдан, когда база перестала помещаться на узел, а рост записи требует горизонтального масштабирования. Если нагрузка читающая, часто достаточно реплик.
Заранее примите ограничения: кросс-шардовые транзакции в общем случае не поддерживаются, JOIN между шардами дорог, внешние ключи не работают между шардами. Приложение проектируется вокруг ключа шардирования, а не вокруг произвольных запросов.
Из чего состоит кластер Vitess
vtctld управляет метаданными и топологией, vtgate принимает подключения по протоколу MySQL и маршрутизирует запросы, vttablet стоит рядом с каждым MySQL, а vtorc следит за восстановлением. Топология хранится в etcd или Consul; для production нужен кворум из трёх узлов.
Ключевое пространство (keyspace) — логическая база, шард — её горизонтальная часть. Внутри шарда есть primary и реплики. Приложение подключается только к vtgate, поэтому смена primary или переезд шарда не требует правок в коде.
Быстрый стенд: vttestserver
Для знакомства не нужно собирать кластер вручную. Официальный образ vttestserver поднимает MySQL, vtgate и vttablet в одном контейнере. Это учебный стенд: данные и настройки не рассчитаны на production.
docker run --name vttestserver -p 33577:33577 -e PORT=33577 -e MYSQL_BIND_HOST=0.0.0.0 vitess/vttestserver:mysql80
mysql -h 127.0.0.1 -P 33577 -u root
SHOW DATABASES;
Порт 33577 здесь — MySQL-протокол vtgate. Если подключение не проходит, проверьте, что контейнер запущен и порт не занят. Для чистой работы удалите старый контейнер.
Ключевое пространство, шарды и VSchema
Сначала создайте unsharded-keyspace и перенесите текущую базу. Затем опишите шардированную версию в VSchema: какие таблицы шардируются, по какому столбцу и какой vindex используется. Для равномерного распределения подходит hash по высококардинальному ключу, например customer_id.
vtctldclient --server localhost:15999 CreateKeyspace commerce
vtctldclient --server localhost:15999 CreateShard --keyspace commerce --shard -
vtctldclient --server localhost:15999 GetTablets --keyspace commerce
vtctldclient --server localhost:15999 ApplyVSchema --vschema-file vschema.json commerce
VSchema задаёт отображение таблиц и порядок генерации идентификаторов. Если оставить MySQL AUTO_INCREMENT, на разных шардах появятся одинаковые значения — используйте последовательность Vitess.
{
"sharded": true,
"vindexes": {
"hash": { "type": "hash" }
},
"tables": {
"orders": {
"column_vindexes": [
{ "column": "customer_id", "name": "hash" }
],
"auto_increment": {
"column": "id",
"sequence": "orders_seq"
}
},
"orders_seq": { "type": "sequence" }
}
}
Схема, последовательности и онлайн-миграции
Таблицу последовательности держите в unsharded-keyspace, а в шардированном используйте через VSchema. Схему применяйте через vtctld, а не прямым ALTER на каждом tablet: так изменение пройдёт согласованно. Для больших таблиц включайте онлайн-стратегию DDL.
CREATE TABLE orders_seq (
id BIGINT NOT NULL,
next_id BIGINT NOT NULL,
cache BIGINT NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO orders_seq (id, next_id, cache) VALUES (1, 1, 1000);
CREATE TABLE orders (
id BIGINT NOT NULL,
customer_id BIGINT NOT NULL,
total DECIMAL(12,2) NOT NULL,
created_at DATETIME NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
После применения схемы подключитесь к vtgate и проверьте маршрутизацию. SQL с customer_id должен уходить в нужный шард; запрос без ключа шардирования станет scatter-запросом по всем шардам.
vtctldclient --server localhost:15999 ApplySchema --sql-file schema.sql commerce
mysql -h 127.0.0.1 -P 15306 -u app -p
INSERT INTO orders (customer_id, total, created_at) VALUES (42, 199.90, NOW());
SELECT * FROM orders WHERE customer_id = 42;
Переезд без простоя: MoveTables и Reshard
Когда база уже работает, не переключайте приложение вручную. MoveTables переносит таблицы в целевую шардированную базу, копирует данные и держит изменения актуальными. Целевой keyspace и его шарды создайте заранее. Проверьте отставание, переключите трафик, затем завершите workflow. Для изменения числа шардов используйте Reshard.
vtctldclient MoveTables --workflow orders_sharded --source-keyspace commerce --target-keyspace commerce_sharded create
vtctldclient MoveTables --workflow orders_sharded --target-keyspace commerce_sharded SwitchTraffic
vtctldclient MoveTables --workflow orders_sharded --target-keyspace commerce_sharded Complete
vtctldclient Reshard --workflow split80 --target-keyspace commerce --source-shards - --target-shards -80,80- create
Перед SwitchTraffic прогоните read-only нагрузку на целевом keyspace, сравните число строк и проверьте отставание репликации. После переключения не удаляйте исходные данные: они нужны для отката и разбора расхождений.
Что ломается в production
- Кросс-шардовые JOIN и транзакции: переписывайте запросы или используйте lookup-таблицы.
- Горячий шард: ключ шардирования выбран неудачно;
statusилиregionс малым числом значений дадут перекос. - Дубликаты идентификаторов: забыта последовательность Vitess или остался MySQL auto_increment.
- Прямой DDL на tablet: схема расходится между шардами; используйте
ApplySchemaи онлайн-стратегию. - Отставание реплик: проверяйте
SHOW REPLICA STATUSна tablet и не отправляйте туда критичное чтение. - Шторм подключений: приложение открывает слишком много сессий к vtgate; ограничьте пул и используйте таймауты.
Диагностика
Начинайте с топологии: видит ли vtctld все tablet, в каком состоянии шарды и кто primary. Затем проверяйте маршрутизацию через vtgate и только потом MySQL.
vtctldclient GetKeyspaces
vtctldclient GetShards --keyspace commerce
vtctldclient GetTablets --keyspace commerce
mysql -h 127.0.0.1 -P 15306 -u app -p -e "SHOW VITESS_SHARDS"
mysql -h 127.0.0.1 -P 15306 -u app -p -e "SHOW VITESS_TABLETS"
Если запрос идёт не туда, проверьте VSchema и значение ключа. Если tablet не поднимается, смотрите его журнал и доступность MySQL. Если после переезда расходятся данные, сравните контрольные суммы по шардам и не завершайте workflow до устранения причины.
Чек-лист
- Ключ шардирования выбран по нагрузке и обеспечивает равномерное распределение.
- Все таблицы с автоинкрементом используют последовательности Vitess.
- Кросс-шардовые запросы известны и осознанно ограничены.
- Для каждого шарда настроены реплики, резервное копирование и мониторинг отставания.
- Переезд проходит через MoveTables или Reshard, а не через ручное копирование.
- Есть план отката и проверка целостности до завершения workflow.
Итог
Vitess решает задачу горизонтального масштабирования MySQL, но требует дисциплины в проектировании данных. Начните с локального стенда, затем перенесите базу в unsharded-keyspace и только после этого включайте шардирование. VSchema, последовательности и онлайн-переезды — три опоры, без которых кластер быстро превращается в набор несогласованных MySQL. Если нагрузка ещё позволяет реплики и оптимизацию запросов, не спешите с шардингом.