Использование спейсов на движке vinyl
Доступно с версии 3.0.0.
В этом руководстве описаны создание спейса vinyl, его настройка, а также выполнение операций с этим спейсом через модуль CRUD.
Рекомендации по настройке параметров vinyl приведены в разделе Методика настройки движка vinyl в Tarantool DataBase.
Для выполнения примера вам понадобятся:
-
установленный Docker-образ Tarantool DB;
-
приложение Docker Compose;
-
утилита tt CLI;
-
исходные файлы примера
vinyl.
Для успешного запуска стенда должны быть свободны следующие порты:
- 2379
- 3300--3308
- 8081
Перейдите в папку с примером vinyl:
cd ./docs/docs/ru/assets/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 необходимо учитывать следующие особенности, отличающие его от движка memtx:
- функция
len()возвращает только приблизительное количество кортежей в спейсе. Если необходимо точное количество кортежей, используйте функциюcount()илиpairs():length(), но имейте в виду, что эти операции значительно медленнее; - операция
deleteне возвращает удалённый кортеж. Если нужно получить значение удаленного кортежа, перед его удалением выполните операциюget; - возможно переключение контекста файбером при чтении из vinyl, поскольку данные могут отсутствовать в памяти и придется обращаться к диску.
Подробнее о различиях между vinyl и memtx можно узнать в документации Tarantool.
В руководстве при запуске кластера применяется миграция из файла
./cluster/migrations/scenario/001_messages.lua примера vinyl.
В этой миграции создан на движке vinyl шардированный спейс messages для хранения пользовательских сообщений:
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' })
Чтобы начать работу с базой данных через интерактивную консоль 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...
Чтобы остановить стенд, выполните в локальном терминале следующую команду:
make stop