Пример работы с кластером Picodata¶
В данном разделе приведены практические примеры команд, которые помогут сделать первые шаги в управлении распределенным кластером Picodata. В частности, в данном разделе рассмотрены следующие вопросы:
- Запуск кластера
- Мониторинг состояния кластера
- Первые действия в только что созданном кластере
- Запись и чтение данных в кластере
- Балансировка данных в кластере
Запуск кластера¶
Запуск кластера сводится к выполнению команды picodata run
с нужным
набором параметров для каждого инстанса (узла). Полный перечень
возможных параметров запуска и их описание содержатся в подразделе
Описание параметров запуска, а также в выводе команды
picodata run --help
. С точки зрения внутренней архитектуры, кластер
корректно называть Raft-группой — в дальнейшем при мониторинге и
управлении конфигурацией будет уместнее использовать именно этот термин.
Для данного примера допустим, что в локальном кластере
(127.0.0.1/localhost) будет 4 инстанса с фактором репликации равным 2,
что означает наличие 2-х репликасетов. Запустим первый инстанс, указав
необходимые параметры:
picodata run --init-replication-factor=2 --listen :3301 --data-dir=inst1
Следует обратить внимание на следующие моменты:
- Параметр
init-replication-factor
задается лишь один раз в момент создания кластера и дальше не требуется. Перезапускать данный инстанс в дальнейшем нужно без этого параметра. - Параметр
listen
может содержать только номер порта (по умолчанию для первого инстанса используется 3301), что означает указание использовать текущий хост. В настоящем распределенном кластере указывать IP-адрес в данном параметре обязательно. - Параметр
data-dir
указывает на директорию, в которой будут храниться персистентные данные инстансы (файлы*.snap
и*.xlog
). Если при первом запуске задать несуществующую директорию, то она будет автоматически создана. - Будет создан кластер со стандартным названием
demo
, т.к. явно не указан параметрcluster-id
(см. подробнее).
Аналогично следует запустить остальные 3 инстанса, указав им отличные от
3301 разные порты и другие рабочие директории. В случае с кластером на
удаленных узлах потребуется также указать данным инстансам параметр
peer
(см. подробнее).
Мониторинг состояния кластера¶
Для мониторинга состояния кластера удобно использовать команды,
показывающие состояние Raft-группы, отдельных инстансов и собранных из
них репликасетов. Для использования указанных команд следует
сначала подключиться к какому-либо инстансу с помощью команды
tarantoolctl connect
.
Примеры команд и их выводов приведены ниже.
Узнать лидера Raft-группы, а также ID и статус текущего инстанса:
pico.raft_status()
Пример вывода:
---
- term: 2
leader_id: 1
raft_state: Leader
id: 1
...
Просмотр состава Raft-группы и данных инстансов:
box.space.raft_group:fselect()
Пример вывода:
---
- - +----------+---------+-------+---------+---------+---------+---------+---------+---------+---------+
- |instance_i|instance_|raft_id|peer_addr|replicase|replicase|commit_in|current_g|target_gr|failure_d|
- +----------+---------+-------+---------+---------+---------+---------+---------+---------+---------+
- | "i1" |"68d4a766| 1 |"localhos| "r1" |"e0df68c5| 12 |["Online"|["Online"| {} |
- | "i2" |"24c4ac5f| 2 |"localhos| "r1" |"e0df68c5| 19 |["Online"|["Online"| {} |
- | "i3" |"5d7a7353| 3 |"localhos| "r2" |"eff4449e| 28 |["Online"|["Online"| {} |
- | "i4" |"826cbe5e| 4 |"localhos| "r2" |"eff4449e| 37 |["Online"|["Online"| {} |
- +----------+---------+-------+---------+---------+---------+---------+---------+---------+---------+
...
Просмотр списка репликасетов, их веса и версии схемы данных:
box.space.replicasets:fselect()
Пример вывода:
---
- - +-------------+--------------------------------------+---------+------+----------------------+
- |replicaset_id| replicaset_uuid |master_id|weight|current_schema_version|
- +-------------+--------------------------------------+---------+------+----------------------+
- | "r1" |"e0df68c5-e7f9-395f-86b3-30ad9e1b7b07"| "i1" | 1 | 0 |
- | "r2" |"eff4449e-feb2-3d73-87bc-75807cb23191"| "i3" | 1 | 0 |
- +-------------+--------------------------------------+---------+------+----------------------+
...
Эти и другие команды сведены в
Bash-скрипт,
который можно загрузить и выполнить для более удобного мониторинга
кластера Picodata (например, командой watch ./picodata-list.sh
).
Внешний вид выполняющегося скрипта показан ниже.
connected to localhost:3301
---
- instance_id: i1
- raft_state: Leader
- voters: [1, 2, 3]
- learners: [4]
- instances:
- +----------+---------+-------+---------+---------+---------+---------+---------+---------+---------+
- |instance_i|instance_|raft_id|peer_addr|replicase|replicase|commit_in|current_g|target_gr|failure_d|
- +----------+---------+-------+---------+---------+---------+---------+---------+---------+---------+
- | "i1" |"68d4a766| 1 |"localhos| "r1" |"e0df68c5| 12 |["Online"|["Online"| {} |
- | "i2" |"24c4ac5f| 2 |"localhos| "r1" |"e0df68c5| 19 |["Online"|["Online"| {} |
- | "i3" |"5d7a7353| 3 |"localhos| "r2" |"eff4449e| 28 |["Online"|["Online"| {} |
- | "i4" |"826cbe5e| 4 |"localhos| "r2" |"eff4449e| 37 |["Online"|["Online"| {} |
- +----------+---------+-------+---------+---------+---------+---------+---------+---------+---------+
- replicasets:
- +-------------+--------------------------------------+---------+------+----------------------+
- |replicaset_id| replicaset_uuid |master_id|weight|current_schema_version|
- +-------------+--------------------------------------+---------+------+----------------------+
- | "r1" |"e0df68c5-e7f9-395f-86b3-30ad9e1b7b07"| "i1" | 1 | 1 |
- | "r2" |"eff4449e-feb2-3d73-87bc-75807cb23191"| "i3" | 1 | 1 |
- +-------------+--------------------------------------+---------+------+----------------------+
...
Данный скрипт выполняет, в частности, следующие действия:
- При выполнении без аргументов подключается к первому локальному
инстансу localhost:3301 с помощью консоли
tarantoolctl
. В качестве аргумента скрипту можно передать произвольное значение<host:port>
. - Выводит идентификатор (значение
instance_id
) текущего инстанса. - Выводит статус текущего инстанса в Raft.
- Выводит количество голосующих/неголосующих узлов (
voters
/learners
) в кластере. - Выводит таблицы со списками инстансов и репликасетов.
- Позволяет узнать текущий и целевой уровень (
grade
) каждого инстанса, а также вес (weight
) репликасета. Уровни отражают конфигурацию остальных инстансов относительно текущего, а вес репликасета — его наполненность репликами согласно фактору репликации (см. подробнее).
Создание схемы данных¶
Перед тем как начать пользоваться СУБД, необходимо создать таблицу,
которая в терминологии Tarantool называется space
. Таблица является
необходимым элементом схемы данных, распространяемой на все узлы
кластера. Каждое действие по изменению схемы данных в Picodata
называется миграцией. Иными словами, миграция — это переход кластера
на использование более новой схемы данных. Любое действие по
созданию/изменению/удалению таблиц, работы с индексами хранения и т.д.
является изменением схемы данных. Каждое изменение инкрементирует версию
схемы данных в кластере.
После подключения к инстансу кластера посредством утилиты
tarantoolctl
, начальным действием в пустом кластере будет добавление
первого space
. Пусть в нем будет два поля: идентификатор записи и
идентификатор бакета, в которой эта запись хранится:
pico.add_migration(1, [[
CREATE TABLE "test" (
"id" int,
"bucket_id" unsigned,
PRIMARY KEY ("id")
);
]])
На данном этапе схема данных существует лишь локально, в коллекции
текущего инстанса. Посмотреть доступные инстансу схемы данных можно
командой box.space.migrations:fselect()
. Результат будет выглядеть
следующим образом:
localhost:3301> box.space.migrations:fselect()
---
- - +-----+-------------------------------------------------------------------------------------------+
- | id | body |
- +-----+-------------------------------------------------------------------------------------------+
- | 1 |"CREATE TABLE \"test\" (\n\"id\" int,\n\"bucket_id\" unsigned,\nPRIMARY KEY (\"id\")\n);\n"|
- +-----+-------------------------------------------------------------------------------------------+
...
Теперь можно применить схему в рамках кластера, введя команду
pico.push_schema_version(1)
. Для того чтобы посмотреть параметры
созданного space
следует использовать команду box.space.test
, где
test — название таблицы. Также следует обратить внимание, что в выводе
команды box.space.replicasets:fselect()
обновится номер текущей схемы
в кластере:
---
- - +-------------+--------------------------------------+---------+------+----------------------+
- |replicaset_id| replicaset_uuid |master_id|weight|current_schema_version|
- +-------------+--------------------------------------+---------+------+----------------------+
- | "r1" |"e0df68c5-e7f9-395f-86b3-30ad9e1b7b07"| "i1" | 1 | 1 |
- | "r2" |"eff4449e-feb2-3d73-87bc-75807cb23191"| "i3" | 1 | 1 |
- +-------------+--------------------------------------+---------+------+----------------------+
...
В дальнейшем каждое изменение схемы данных в кластере будет приводить к увеличению этого номера.
Вызов функций записи и чтения из БД¶
Для того, чтобы в таблицу/space можно было записывать данные, требуется сначала создать индекс БД. Для этого создадим еще одну миграцию схемы данных:
pico.add_migration(2, [[CREATE INDEX "bucket_id" on "test" ("bucket_id");]])
pico.push_schema_version(2)
После этого в таблицу можно вставлять строки, используя функцию записи из состава библиотеки vshard
:
vshard.router.callrw (1, "box.space.test:insert", {{1, 1}})
Здесь первая и третья 1 — номер бакета, вторая — номер записи. Можно делать множество записей с разными номерами в один и тот же бакет. Пример для 4-й записи в 2000-м бакете:
vshard.router.callrw (2000, "box.space.test:insert", {{4, 2000}})
Просмотр сделанной записи:
vshard.router.callro (2000, "box.space.test:select")
Запись и чтение данных¶
Для того чтобы записать в БД какие-либо настоящие данные (например,
текстовую строку), нам потребуется создать новый space
с еще одним
полем для хранения такого текста, а также новым индексом. Это означает
проведение еще двух миграций схемы данных.
Добавим space
с названием test1
:
pico.add_migration(3, [[
CREATE TABLE "test1" (
"id" int,
"bucket_id" unsigned,
"text" string,
PRIMARY KEY ("id")
);
]])
pico.push_schema_version(3)
Создадим на нем индекс:
pico.add_migration(4, [[CREATE INDEX "bucket_id" on "test1" ("bucket_id");]])
pico.push_schema_version(4)
Для просмотра всех полей таблицы, включая текстовые, подойдет следующая команда:
box.space.test1:format()
Пример записи текстовой строки:
vshard.router.callrw (1, "box.space.test1:insert", {{1, 1, "Sample text"}})
Проверка:
vshard.router.callro (1, "box.space.test1:select")
Балансировка данных¶
Работа с бакетами¶
Относительно бакетов в Picodata используются умолчания, принятые в СУБД Tarantool, согласно которым в кластере всегда доступны 3000 бакетов. Размер бакета динамичен: он определяется размером хранимых в нем данных. Бакеты равномерно распределяются между репликасетами. В приведенном здесь примере кластера из двух репликасетов, один из них хранит диапазон бакетов от 0 до 1500, а второй — от 1501 до 3000.
Для того чтобы просмотреть хранящиеся в текущем репликасете бакеты, используйте следующую команду:
box.space.test1:fselect()
Соответственно, если нужного бакета в списке нет, то он хранится в другом репликасете, и данную команду нужно выполнять на нем. Просмотреть список бакетов на текущем инстансе можно так:
box.space._bucket:fselect()
Балансировка данных в Picodata происходит автоматически при изменении
конфигурации кластера, например при добавлении новых инстансов. Во время
балансировки изменяется распределение бакетов между репликасетами. К
примеру, если в кластере добавится новый полный (с весом 1) репликасет,
то часть бакетов автоматически переедет на него. Это можно будет
заметить при выполнении команды box.space._bucket:fselect()
.
Создание шардированной таблицы¶
Рассмотрим пример с шардированием данных в кластере Picodata.
Запустим кластер из двух экземпляров:
picodata run --listen localhost:3301 --instance-id i1 --cluster-id c1 --peer localhost:3301,localhost:3302,localhost:3303
picodata run --listen localhost:3302 --instance-id i2 --cluster-id c1 --peer localhost:3301,localhost:3302,localhost:3303
Создадим шардированную таблицу (space). Ключевым моментом является создание индекса bucket_id
в space (его наличие помечает space как шардированный):
pico.add_migration(1, 'create table t2(a int, "bucket_id" unsigned, primary key (a));')
pico.add_migration(2, 'create index "bucket_id" on t2 ("bucket_id");')
pico.migrate(2)
Заполним шардированный space (все 3000 бакетов) тестовыми данными:
for i=1,3000 do vshard.router.callrw(i, 'box.space.T2:insert', {{i, i}}) end
Проверим, что данные поровну распределились между экземплярами. На каждом из них (i1
, i2
) выполним запрос:
vshard.storage.info().bucket
В результате мы получим по 1500 бакетов на каждом экземпляре:
---
- receiving: 0
active: 1500
total: 1500
garbage: 0
pinned: 0
sending: 0
...
Добавим еще один экземпляр:
picodata run --listen localhost:3303 --instance-id i3 --cluster-id c1 --peer localhost:3301,localhost:3302,localhost:3303
Запустим ребалансировку данных. Важный момент: ребалансер бакетов работает на экземпляре с наименьшим значением instance_uuid
из спейса _picodata_instance
:
\set language sql
select "instance_uuid", "instance_id" from "_picodata_instance"
\set language lua
В результате получим:
---
- metadata:
- name: instance_uuid
type: string
- name: instance_id
type: string
rows:
- ['68d4a766-4144-3248-aeb4-e212356716e4', 'i1']
- ['24c4ac5f-4981-3441-879c-aee1edb608a6', 'i2']
- ['5d7a7353-3e82-30fd-af0d-261436544389', 'i3']
...
В данном случае наименьшее значение UUID имеет экземпляр i2
(т.к. в число 24c4ac5f-4981-3441-879c-aee1edb608a6
в байтовом представлении меньше остальных). Поэтому ребалансировка будет запущена на нем (но мы для примера запустим ее вручную):
vshard.storage.rebalancer_wakeup()
Проверим, что данные перераспределились между тремя экземплярами. На каждом из них (i1
, i2
и i3
) выполним запрос:
vshard.storage.info().bucket
В результате мы получим по 1000 бакетов на каждом экземпляре:
---
- receiving: 0
active: 1000
total: 1000
garbage: 0
pinned: 0
sending: 0
...
Подробнее о внутренней архитектуре кластера Picodata см. в разделе Общая схема инициализации кластера. Параметры запуска из командной строки описаны в разделе Описание параметров запуска.
Дата создания: 10 апреля 2023 г.