TDB Documentation portal logo
Помощь

Шардирование

Масштабирование баз данных — это увеличение вычислительных ресурсов для хранения и обработки нарастающего количества данных. Если отдельный сервер не справляется с нагрузкой, используются средства масштабирования:

  • вертикальное масштабирование — увеличиваются вычислительные мощности узлов, при этом следует учитывать аппаратные ограничения;
  • горизонтальное масштабирование — данные делятся на части, которые хранятся на отдельных узлах независимо друг от друга.

Шардирование с помощью встроенного модуля 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_id    helpers.register_sharding_key(space_bands.name, {'id'}) -- Указать, по какому полю шардировать спейс    return trueendreturn {    apply = {        scenario = apply,    }}

Пример работы с шардированным кластером приведен в разделе Руководство для начинающих.