Использование спейсов на движке 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:
adminPassword:
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