Использование спейсов на движке vinyl¶
Доступно с версии 3.0.0.
В этом руководстве описаны создание спейса vinyl, его настройка, а также выполнение операций с этим спейсом через модуль CRUD.
Рекомендации по настройке параметров vinyl приведены в разделе Методика настройки движка vinyl в Tarantool DB.
Пререквизиты¶
Для выполнения примера вам понадобятся:
установленный Docker-образ Tarantool DB;
приложение Docker Compose;
утилита tt CLI;
исходные файлы примера
vinyl
.Примечание
Есть два способа получить исходные файлы примера:
Архив с полной документацией Tarantool DB, полученный по почте или скачанный в личном кабинете tarantool.io. Пример архива:
tarantooldb-documentation-3.0.0.tar.gz
. Примерvinyl
расположен в таком архиве в директории./doc/examples/vinyl/
.Отдельный архив vinyl.tar.gz, скачанный c сайта Tarantool.
Запуск стенда¶
Для успешного запуска стенда должны быть свободны следующие порты:
2379
3300–3308
8081
Перейдите в папку с примером vinyl
:
cd ./doc/examples/vinyl/
Запустите стенд:
make start
После выполнения команды будет развернут следующий стенд:
кластер Tarantool DB:
2 роутера;
2 набора реплик по 3 хранилища;
кластер etcd из 3 узлов;
веб-интерфейс Tarantool Cluster Manager (TCM).
После запуска должны работать все контейнеры, кроме init_host
.
Контейнер init_host
используется только для инициализации и завершает свою работу после настройки кластера.
Также после запуска кластера становится доступен веб-интерфейс TCM. Через TCM вы можете управлять кластером и подключаться к его узлам. Для входа в TCM откройте в браузере адрес http://localhost:8081. Логин и пароль для входа:
Username:
admin
Password:
secret
Особенности работы с vinyl¶
При работе с дисковым движком vinyl необходимо учитывать следующие особенности, отличающие его от движка memtx:
функция
len()
возвращает только приблизительное количество кортежей в спейсе. Если необходимо точное количество кортежей, используйте функциюcount()
илиpairs():length()
, но имейте в виду, что эти операции значительно медленнее;операция
delete
не возвращает удалённый кортеж. Если нужно получить значение удаленного кортежа, перед его удалением выполните операциюget
;возможно переключение контекста файбером при чтении из vinyl, поскольку данные могут отсутствовать в памяти и придется обращаться к диску.
Подробнее о различиях между vinyl и memtx можно узнать в документации Tarantool.
Создание спейса vinyl¶
В руководстве при запуске кластера применяется миграция из файла
./cluster/migrations/scenario/001_messages.lua
примера vinyl
.
В этой миграции создан на движке vinyl шардированный спейс messages
для хранения пользовательских сообщений:
if is_storage() then
box.schema.space.create('messages', { engine = 'vinyl', if_not_exists = true })
box.space.messages:format({
{ name = 'id', type = 'number' },
{ name = 'bucket_id', type = 'unsigned' },
{ name = 'text', type = 'string' },
{ name = 'created_at', type = 'datetime' },
})
box.space.messages:create_index('bucket_id', { parts = { 'bucket_id', 'id' }, if_not_exists = true })
helpers.register_sharding_key('messages', { 'id' })
Составной первичный индекс¶
Спейс messages
использует составной первичный индекс по двум полям:
box.space.messages:create_index('bucket_id', { parts = { 'bucket_id', 'id' }, if_not_exists = true })
Здесь:
bucket_id
– идентификатор виртуального сегмента, используемый для шардирования;id
– идентификатор сообщения.
При использовании движка vinyl создание отдельного вторичного индекса по bucket_id
избыточно и неэффективно по
двум причинам:
каждый вторичный индекс в vinyl представляет собой отдельное LSM-дерево, требующее дополнительное место на диске;
при поиске по вторичному индексу Tarantool сначала находит первичный ключ во вторичном индексе, а затем обращается к первичному индексу для получения полной записи. При выполнении range-запроса это приводит к случайным чтениям с диска.
Использование составного первичного индекса { bucket_id, id }
дает возможность шардирования без издержек вторичного
индекса.
Для настройки производительности индексов в vinyl доступны следующие параметры конфигурации:
vinyl.bloom_fpr
– коэффициент ложноположительного срабатывания фильтра Блума. Чем ниже значение, тем точнее фильтр, но больше потребление памяти. Значение по умолчанию: 0.05;vinyl.page_size
– размер страницы при чтении и записи в байтах. Значение по умолчанию: 8192;vinyl.range_size
– максимальный размер диапазона по умолчанию (в байтах);vinyl.run_count_per_level
– максимальное количество.run
-файлов на каждом уровне LSM-дерева. Чем больше значение, тем шире LSM-дерево. Значение по умолчанию: 2;vinyl.run_size_ratio
– соотношение между размерами уровней в LSM-дереве. Чем меньше значение, тем выше LSM-дерево. Значение по умолчанию: 3.5.
Задать настройки спейса, связанные с движком vinyl, можно двумя способами:
в YAML-конфигурации кластера в секции
vinyl
;в опции index_opts при создании индекса через
space_object:create_index()
.
Подробную информацию о поддерживаемых опциях конфигурации для движка vinyl можно найти в документации Tarantool.
Регистрация ключа шардирования¶
Модуль CRUD
по умолчанию вычисляет bucket_id
по первичному ключу, поэтому в миграции необходимо явно указать id
в качестве ключа шардирования:
helpers.register_sharding_key('messages', { 'id' })
Работа с данными через модуль CRUD¶
Чтобы начать работу с базой данных через интерактивную консоль Tarantool, нужно подключиться к узлу кластера. Это можно сделать двумя способами:
через веб-интерфейс TCM;
через терминал с помощью утилиты tt CLI:
tt connect admin:secret-cluster-cookie@localhost:3301
Подключитесь к роутеру router-msk
, используя первый способ – через TCM. Для этого:
Перейдите в раздел Stateboard.
Нажмите на набор реплик
router-msk
.Выберите узел
router-msk
и в открывшемся окне перейдите на вкладку Terminal (TT Connect
).
Теперь вы находитесь в интерактивной консоли Tarantool и можете выполнять запросы к кластеру.
Определение вспомогательной функции¶
Для удобства ввода данных добавьте в консоль следующую вспомогательную функцию:
now()
– функция возвращает текущее время:function now() local datetime = require('datetime') return datetime.now() end
Вставка данных¶
Во вкладке Terminal добавьте несколько сообщений в спейс messages
с помощью метода crud.insert_object_many
:
crud.insert_object_many('messages', {
{ id = 1, text = 'Привет!', created_at = now() },
{ id = 2, text = 'Hello world', created_at = now() },
{ id = 3, text = 'Bye', created_at = now() },
{ id = 4, text = 'Ok', created_at = now() },
{ id = 5, text = 'Hi', created_at = now() },
})
Выборка данных¶
Посмотрите содержимое спейса, используя операцию crud.select()
:
crud.select('messages')
Вывод:
---
- rows:
- [1, 12477, 'Привет!', '2025-08-28T11:12:09.028308Z']
- [3, 11804, 'Bye', '2025-08-28T11:12:09.028313Z']
- [5, 1172, 'Hi', '2025-08-28T11:12:09.028333Z']
- [2, 21401, 'Hello world', '2025-08-28T11:12:09.028312Z']
- [4, 28161, 'Ok', '2025-08-28T11:12:09.028330Z']
metadata: [{'name': 'id', 'type': 'number'}, {'name': 'bucket_id', 'type': 'unsigned'},
{'name': 'text', 'type': 'string'}, {'name': 'created_at', 'type': 'datetime'}]
- null
...
Получение одной записи¶
Прочитайте запись с id = 1
:
crud.get('messages', { box.NULL, 1 })
Вывод:
---
- rows:
- [1, 12477, 'Привет!', '2025-08-28T11:12:09.028308Z']
metadata: [{'name': 'id', 'type': 'number'}, {'name': 'bucket_id', 'type': 'unsigned'},
{'name': 'text', 'type': 'string'}, {'name': 'created_at', 'type': 'datetime'}]
- null
...
Обновление записи¶
Обновите сообщение с id = 2
, изменив его текст:
crud.update('messages', { box.NULL, 2 }, { {'=', 'text', 'Some text'} })
Вывод:
---
- rows:
- [2, 21401, 'Some text', '2025-08-28T11:12:09.028312Z']
metadata: [{'name': 'id', 'type': 'number'}, {'name': 'bucket_id', 'type': 'unsigned'},
{'name': 'text', 'type': 'string'}, {'name': 'created_at', 'type': 'datetime'}]
- null
...
Удаление записи¶
Удалите сообщение с id = 1
:
crud.delete('messages', { box.NULL, 1 })
Вывод:
---
- rows: []
metadata: [{'name': 'id', 'type': 'number'}, {'name': 'bucket_id', 'type': 'unsigned'},
{'name': 'text', 'type': 'string'}, {'name': 'created_at', 'type': 'datetime'}]
- null
...
Примечание
Операция delete
в vinyl не возвращает удалённый кортеж.
Остановка стенда¶
Чтобы остановить стенд, выполните в локальном терминале следующую команду:
make stop