Tarantool 3.4
Дата выпуска: 14 апреля 2025 г.
Релизы на GitHub:
В версии Tarantool 3.4 добавлены следующие основные возможности и улучшения для редакций Community и Enterprise:
- Community Edition (CE)
- Междвижковые транзакции для memtx и vinyl.
- Новая функция
index:quantile()для поиска квантильного ключа в индексированном диапазоне данных. - Функциональные индексы в менеджере транзакций MVCC.
- Vinyl теперь поддерживает итераторы
np(следующий префикс) иpp(предыдущий префикс). - Исправлены некорректные сравнения чисел и повторы в уникальных индексах.
- Привилегии времени выполнения для
lua_callтеперь предоставляются перед вызовом функцииbox.cfg(). - Функции обратного вызова
stopдля ролей теперь выполняются во время плавного завершения работы (в порядке, обратном запуску ролей). - С помощью новых методов
has_role,is_routerиis_storageв модулеconfigможно проверять, включена ли конкретная роль для экземпляра. - Профилировщики LuaJIT стали более удобны в использовании.
- Встроенный модуль журналирования теперь кодирует аргументы таблицы в формате JSON.
- Исправлены многочисленные недочеты, найденные в MVCC, vinyl, WAL и создании снимков.
- Исправлена проблема с чрезмерным ростом памяти для
рабочих нагрузок, требующих использования
cdata.
- Enterprise Edition (EE)
- Новый движок для работы с колоночными данными в памяти:
memcs. - Новая стратегия начальной загрузки при переключении при отказе:
native. - Новый публичный API для доступа к удаленным кластерам
config.storageв качестве хранилища ключей и значений. - Двухэтапный процесс назначения, позволяющий избежать некорректного поведения координатора переключения при отказе.
- Новый движок для работы с колоночными данными в памяти:
Движок memcs хранит данные в memtx-арене, но, в отличие от
memtx, он хранит данные в виде колонок, а не кортежей.
Каждому полю формата присваивается своя собственная древовидная структура BPS (вектор BPS), в которой хранятся значения только этого поля. Если тип поля помещается в 8 байт, то необработанные значения полей сохраняются непосредственно в листьях дерева, без всякой кодировки. Для значений размером более 8 байт, таких как decimal, uuid или строки, в листьях хранятся указатели на данные, закодированные в формате MsgPack.
Основным преимуществом такой организации данных является значительное
повышение производительности при последовательном сканировании
колоночных данных по сравнению с memtx благодаря локальности кэша
процессора. По этой причине memcs использует специальный C API
для такого колоночного сканирования: см. box_index_arrow_stream() и
box_raw_read_view_arrow_stream().
Максимальная производительность достигается при сканировании встроенных
типов полей. Как и memtx, memcs поддерживает запрос полных кортежей,
но его производительность здесь ниже, чем у memtx, поскольку кортеж
должен быть создан во время выполнения на основе значений отдельных
полей, собранных из каждого дерева колонок.
Прочие функции memcs:
- Поиск по точкам.
- Стабильные итераторы.
- Вставка / замена / удаление / обновление данных.
- Пакетная вставка в формате Apache Arrow.
- Транзакции, в том числе междвижковые транзакции с
memtx(для последнего требуется указывать параметрmemtx_use_mvcc_engine = false). - Поддержка представлений чтения.
- Вторичные индексы с возможностью указания покрываемых колонок и последовательного сканирования индексированных + покрываемых колонок.
К встроенным типам полей относятся только типы с фиксированной длиной:
- Целочисленные: (u)int8/16/32/64.
- С плавающей точкой: float32/64.
К типам полей с внешним хранилищем относятся:
- Строки.
- Все остальные типы, поддерживаемые Tarantool: UUID, Decimal, Datetime и т.д.
По умолчанию значения NULL сохраняются явным образом и занимают столько же места, сколько и любое другое допустимое значение колонки (1, 2, 4 или 8 байт в зависимости от конкретного типа поля). Также поддерживается RLE-кодирование значений NULL.
Для справки: RLE-кодирование колонки, содержащей 90% равномерно распределенных значений NULL, снижает потребление памяти для такой колонки примерно в 5 раз.
Теперь Tarantool поддерживает инструкции для memtx и vinyl, заданные
в одной транзакции, например:
local memtx = box.schema.space.create('memtx', {engine = 'memtx'})memtx:create_index('primary')local vinyl = box.schema.space.create('vinyl', {engine = 'vinyl'})vinyl:create_index('primary')memtx:insert({1, 'a'})vinyl:insert({2, 'b'})box.begin()memtx:replace(vinyl:get(2))vinyl:replace(memtx:get(1))box.commit()
Координатор управляемого переключения при отказе теперь поддерживает
три стратегии начальной загрузки: native, supervised, auto.
Новая стратегия native ослабляет ограничения стратегии auto. Также они отличаются внутренней реализацией (native
реализована на базе стратегии supervised). В остальном стратегия
native работает аналогично стратегии auto.
Стратегия native помогает решить следующие две проблемы:
- Избежать ошибки
Some replica set members were not specified in box.cfg.replicationв следующих случаях:- несколько реплик подключаются одновременно,
- набор реплик включает в себя неанонимные экземпляры CDC,
_clusterсодержит старые, ненужные реплики.
- Заставить базу данных выполнить начальную загрузку по команде координатора, не позволяя экземплярам выполнять начальную загрузку самостоятельно.
Стратегия native рекомендуется для высокодинамичных кластеров с
автоматическим масштабированием, а также в большинстве других случаев.
Чтобы включить стратегию начальной загрузки native, укажите ее в
разделе replication в конфигурации кластера вместе с соответствующей
стратегией переключения при отказе (для стратегии native можно выбрать
любую стратегию переключения при отказе, например supervised):
replication:failover: supervisedbootstrap_strategy: native
Теперь можно предоставлять привилегии на выполнение Lua-функций с
помощью декларативной конфигурации, даже если база данных находится в
режиме "только для чтения" или имеет устаревшую версию схемы. Также
можно разрешить пользователю guest выполнять Lua-функции перед
начальной загрузкой.
Можно указать права доступа к функциям, используя параметр lua_call в
конфигурации, например:
credentials:users:alice:privileges:- permissions: [execute]lua_call: [my_func]
Здесь пользователю alice дается разрешение на выполнение Lua-функции
my_func независимо от режима или статуса базы данных. Также
поддерживается специальный параметр lua_call: [all], предоставляющий
доступ ко всем глобальным Lua-функциям, кроме встроенных, в обход
ограничений базы данных. Привилегии по-прежнему будут записываться в
базу данных, когда это возможно, чтобы сохранить совместимость и
согласованность с другими типами привилегий.
В модуле config теперь доступны три новых метода:
config:has_role('myrole')сообщает, назначена ли рольmyroleдля текущего экземпляра, аconfig:has_role('myrole', {instance = 'i-001'})делает то же самое для указанного экземпляра (i-001).config:is_router()сообщает, является ли текущий экземпляр маршрутизатором vshard, а функцияconfig:is_router({instance = 'i-002'})делает то же самое для указанного экземпляра (i-002).config:is_storage()сообщает, является ли текущий экземпляр хранилищем vshard, аconfig:is_storage({instance = 'i-003'})делает то же самое для указанного экземпляра (i-003).
К удаленным кластерам config.storage теперь можно получить доступ с
помощью метода config.storage_client.connect(endpoints[, {options}]).
Возвращаемый объект является соединением с удаленным хранилищем
значений key-value, доступ к которому выполняется с помощью методов
:get(), :put(), :info(), :txn() с той же сигнатурой, что и в
серверном API config.storage.
В API config.storage_client также есть несколько особых методов:
:is_connected(), :watch(), :reconnect(), :close().
Вот несколько примеров использования:
-- Подключение к кластеру 'config.storage' с использованием конечных точек-- (endpoints), настроенных в разделе 'config.storage'.---- Конечные точки можно указать в виде Lua-таблицы:---- local endpoints = {-- {-- uri = '127.0.0.1:4401',-- login = 'sampleuser',-- password = '123456',-- }-- }local endpoints = config:get('config.storage.endpoints')local client = config.storage_client.connect(endpoints)-- Передать значение подключенному клиенту.client:put('/v', 'a')-- Получить все сохраненные значения.local values = client:get('/')-- Очистить хранилище.local response = client:delete('/')-- Отслеживать изменения ключей.local log = require('log')local w = client:watch('/config/main', function()log.info('config has been updated')end)-- Отменить регистрацию наблюдателя.w:unregister()