Шардирование
Масштабирование баз данных — это увеличение вычислительных ресурсов для хранения и обработки нарастающего количества данных. Если отдельный сервер не справляется с нагрузкой, используются средства масштабирования:
- вертикальное масштабирование — увеличиваются вычислительные мощности узлов, при этом следует учитывать аппаратные ограничения;
- горизонтальное масштабирование — данные делятся на части, которые хранятся на отдельных узлах независимо друг от друга.
Шардирование с помощью встроенного модуля vshard — это принцип горизонтального масштабирования, при котором набор данных
распределяется (шардируется) по множеству узлов, на каждом из которых находится экземпляр сервера Tarantool DB.
Каждый экземпляр обрабатывает лишь подмножество от общего набора данных, так что увеличение нагрузки можно
компенсировать добавлением новых серверов.
Подробная информация о механизме шардирования приведена в документации платформы Tarantool.
Кластер делится на несколько шардов. Каждый шард представляет собой набор реплик, одна из которых — 'nj мастер-узел, обрабатывающий все запросы на чтение и запись. Для выполнения операций над шардированными данными в кластере используется модуль CRUD.
Кортежи распределяются не по физическим узлам, а по множеству абстрактных виртуальных сегментов (buckets).
Каждый сегмент содержит уникальный набор кортежей.
Сегменты распределяются между всеми шардами кластера, причем каждый шард хранит уникальное подмножество сегментов.
Мастер-узел в наборе реплик хранит данные сегментов, распределенные на этот шард, в системном спейсе _bucket.
Полная информация о соответствии всех шардов и их сегментов хранится в системном спейсе Tarantool DB.
Каждому сегменту присваивается уникальный номер от 1 до N (общее количество сегментов), который используется как
идентификатор сегмента (bucket_id).
Чтобы шардировать спейс, в его схему нужно добавить поле bucket_id и индекс по этому полю.
Хеширование bucket_id в большое количество сегментов позволяет незаметно для пользователя изменять количество
серверов в кластере.
При добавлении или удалении серверов механизм балансировки распределяет сегменты между шардами.
Шардированный кластер состоит из следующих элементов:
- один или несколько шардов (наборов реплик). Набор реплик состоит из узлов хранилища, каждый из узлов имеет роль мастер или реплика. Узел хранилища содержит подмножество набора данных;
- один или несколько экземпляров роутеров. Роутер — это узел, который маршрутизирует запросы чтения и записи от клиентского приложения к шардам. Все запросы из приложения приходят в шардированный кластер через роутер;
- балансировщик — фоновый процесс балансировки, распределяющий сегменты по шардам. Во время балансировки происходит миграция сегментов по наборам реплик.
При создании шардированного спейса в миграции необходимо выполнить следующие условия:
- добавить поле
bucket_idдля записи номера сегмента; - задать вторичный индекс по полю
bucket_id. Модульvshardиспользует этот индекс в качестве индекса шардирования (shard_index): по немуvshardопределяет, что спейс участвует в шардировании и может работать с данными. Этот индекс не используется для расчётаbucket_id; - указать ключ шардирования для модуля CRUD — поле или набор полей, по которым нужно шардировать спейс.
По ключу шардирования CRUD на роутере рассчитывает значение
bucket_id(в примере нижеbucket_idвычисляется из значенияid). В миграции это можно задать в функцииhelpers.register_sharding_key(), которая записывает информацию о ключе в системный спейс_ddl_sharding_key.
Когда клиентское приложение обращается к кластеру, модуль CRUD на основе ключа шардирования определяет, куда писать и
откуда читать кортежи в шардированном спейсе.
CRUD вычисляет номер сегмента bucket_id по полям, указанным в ключе шардирования — по ним считается целочисленный хэш,
составляющий номер сегмента.
Если ключ шардирования явно не указан, модуль CRUD по умолчанию рассчитывает bucket_id по полям первичного ключа.
Информация о том, на каком шарде находятся данные сегмента, вычисляется по таблице маршрутизации.
В миграции в качестве ключа шардирования обычно указывается поле первичного индекса (в примере это id):
local helpers = require('tt-migrations.helpers') -- Подключить вспомогательный модульlocal function apply() -- Функция, выполняющая миграцию-- Создать спейсlocal space_bands = box.schema.space.create('bands', {if_not_exists = true,format = {{ name = 'id', type = 'integer' },{ name = 'bucket_id', type = 'unsigned' }, -- Задать служебное поле с ключом шардирования{ name = 'band_name', type = 'string' },{ name = 'year', type = 'integer' },},})space_bands:create_index('primary_key', { parts = {'id'}, if_not_exists = true}) -- Создать первичный индексspace_bands:create_index('bucket_id', { parts = {'bucket_id'}, unique = false, if_not_exists = true}) -- Создать вторичный индекс по полю bucket_idhelpers.register_sharding_key(space_bands.name, {'id'}) -- Указать, по какому полю шардировать спейсreturn trueendreturn {apply = {scenario = apply,}}
Пример работы с шардированным кластером приведен в разделе Руководство для начинающих.