Tarantool 3.0
Дата выпуска: 26 декабря 2023 г.
Релизы на GitHub: 3.0.2,
3.0.1,
3.0.0
В релизе Tarantool 3.0 добавлен новый декларативный подход к конфигурации кластера, новый визуальный инструмент –- Tarantool Cluster Manager, а также множество других новых возможностей и исправлений. В этом документе представлен обзор наиболее важных возможностей для редакций Community и Enterprise.
-
Стабильность .. 3-0-new_declarative_configuration:
Начиная с версии 3.0 в Tarantool появилась возможность настраивать полную топологию кластера с помощью декларативной конфигурации в формате YAML вместо настройки каждого экземпляра с помощью отдельного Lua-скрипта. При новом подходе можно задавать локальную конфигурацию для каждого экземпляра в YAML-файле или хранить данные конфигурации в одном надежном месте, например, в кластере Tarantool или etcd.
В приведенном ниже примере показано, как может выглядеть конфигурация небольшого шардированного кластера. На схеме кластер состоит из 5 экземпляров: одного роутера и 4 хранилищ, которые образуют два набора реплик. Для каждого набора реплик мастер-экземпляр задается вручную.

В приведенном ниже примере показано, как топология такого кластера может выглядеть в файле конфигурации YAML:
/code_snippets/snippets/sharding/instances.enabled/sharded_cluster/config.yaml
Полный пример можно найти в репозитории документации на GitHub: sharded_cluster.
С помощью последней версии утилиты tt можно управлять экземплярами Tarantool, настроенными с помощью нового подхода. Запустить все экземпляры в кластере можно одной командой, а также проверить их статус или остановить их:
$ tt start sharded_cluster• Starting an instance [sharded_cluster:storage-a-001]...• Starting an instance [sharded_cluster:storage-a-002]...• Starting an instance [sharded_cluster:storage-b-001]...• Starting an instance [sharded_cluster:storage-b-002]...• Starting an instance [sharded_cluster:router-a-001]...
В Tarantool Enterprise Edition можно хранить данные конфигурации в одном
надежном месте, например, в кластере etcd. Для
этого нужно настроить параметры подключения в разделе config.etcd
файла конфигурации, например:
/code_snippets/snippets/centralized_config/instances.enabled/config_etcd/config.yaml
При использовании приведенной выше конфигурации экземпляр Tarantool ищет конфигурацию кластера по следующему пути:
http://localhost:2379/myapp/config/*
В Tarantool 3.0 Enterprise Edition добавлен новый визуальный инструмент –- Tarantool Cluster Manager (TCM). TCM предоставляет веб-интерфейс для управления, настройки и мониторинга кластеров Tarantool EE, использующих централизованное хранилище конфигурации.

С помощью TCM можно управлять несколькими кластерами и решать широкий круг задач: от написания конфигурации кластера до интерактивного выполнения команд на конкретных экземплярах.

В TCM реализована система ролевого управления доступом, с помощью которой можно управлять доступом пользователей к кластерам, их конфигурациям и хранимым данным.

Встроенный настраиваемый механизм ведения журнала аудита и аутентификация LDAP обеспечивают соответствие TCM различным корпоративным требованиям безопасности.

Начиная с версии 3.0 в Tarantool добавлена расширенная статистика потребления памяти для конкретного спейса или определенных кортежей.
Обычно для получения размера памяти, занимаемой указанным спейсом, используется метод space_object:bsize():
undefined
app:instance001> box.space.books:bsize()
: –-
- 70348673
Помимо самих данных, спейсу требуется дополнительная память для хранения служебной информации. Общий объем используемой памяти можно посмотреть с помощью box.slab.info():
undefined
app:instance001> box.slab.info().items_used
: –-
- 75302024
С помощью нового метода space_object:stat() <box_space-stat> можно определить, как используются
дополнительные 5 Мб памяти:
undefined
app:instance001> box.space.books:stat()
: –-
-
tuple:
memtx:
: waste_size: 1744011 data_size: 70348673 header_size: 2154132 field_map_size: 0
malloc:
: waste_size: 0 data_size: 0 header_size: 0 field_map_size: 0
Этот отчет содержит следующую информацию:
-
header_sizeиfield_map_size: размер служебной информации. -
data_size: фактический размер данных, равныйspace_object:bsize(). -
waste_size: объем памяти, теряемой из-за внутренней фрагментации в slab-аллокаторе. Чтобы получить подобную информацию о конкретном кортеже, используйте tuple_object:info():
undefined
app:instance001> box.space.books:get('1853260622'):info()
: –-
- data_size: 277
: waste_size: 9 arena: memtx field_map_size: 0 header_size: 10
В новой версии добавлена возможность вручную выбрать лидера начальной загрузки для набора реплик. Лидер начальной загрузки –- это узел, который создает начальный снимок и регистрирует все реплики в наборе реплик.
Сначала нужно задать для параметра
replication.bootstrap_strategy
значение config. Затем укажите лидера начальной загрузки с помощью
параметра <replicaset_name>.bootstrap_leader.
/code_snippets/snippets/replication/instances.enabled/bootstrap_strategy/config.yaml
В версии 3.0 в Tarantool Enterprise Edition добавлен ряд новых возможностей, повышающих уровень безопасности в кластере:
-
Добавлен конфигурационный параметр
secure_erasing, который заставляет Tarantool несколько раз перезаписывать файл данных перед удалением, чтобы сделать восстановление удаленного файла невозможным. При новом подходе к конфигурации эту возможность можно включить следующим образом:security:secure_erasing: trueЭтот параметр также можно задать с помощью переменной окружения
TT_SECURITY_SECURE_ERASING. -
Добавлен параметр
auth_retries, задающий максимальное количество повторных попыток аутентификации перед включением троттлинга. Задать этот параметр можно следующим образом:security:auth_retries: 3 -
Добавлена возможность использовать новый SSL-сертификат с тем же именем путем перезагрузки конфигурации. Для этого используйте функцию
reload(), предоставляемую новым модулемconfig:undefined
app:instance001> require('config'):reload()
: –-
В Tarantool Enterprise Edition добавлены следующие новые возможности для журналирования аудита:
-
В каждую запись аудита добавлен уникальный идентификатор (UUID).
-
Добавлены уровни важности для записей аудита. Теперь каждому системному событию аудита присваивается уровень важности в зависимости от его значимости.
-
Добавлен параметр
audit_log.audit_spaces, который настраивает список спейсов, для которых события операций с данными должны записываться в журнал. -
Добавлен параметр
audit_log.audit_extract_key, который заставляет подсистему аудита записывать в журнал первичный ключ вместо полного кортежа при операциях DML.
: Это может быть полезно для уменьшения размера журнала аудита при работе с большими кортежами.
Пример конфигурации журнала аудита в версии 3.0 может выглядеть
следующим образом, включая новые параметры audit_spaces и
audit_extract_key:
audit_log:to: filefile: audit_tarantool.logfilter: [ddl,dml]spaces: [books]extract_key: true
При такой конфигурации запись аудита для операции DELETE может выглядеть следующим образом:
{"time": "2023-12-19T10:09:44.664+0000","uuid": "65901190-f8a6-45c1-b3a4-1a11cf5c7355","severity": "VERBOSE","remote": "unix/:(socket)","session_type": "console","module": "tarantool","user": "admin","type": "space_delete","tag": "","description": "Delete key ["0671623249"] from space books"}
Запись содержит новые поля uuid и severity. Последнее поле
description содержит только информацию о ключе удалённого кортежа.
Flight recorder, доступный в Enterprise
Edition, –- это инструмент сбора событий, который собирает различную
информацию о работающем экземпляре Tarantool. В версии 3.0 появилась
возможность читать записи flight recorder с помощью API,
предоставляемого модулем flightrec.
Чтобы включить flight recorder в YAML-файле, задайте значение true для
параметра flightrec.enabled:
/code_snippets/snippets/config/instances.enabled/flightrec/config.yaml
Затем с помощью Lua API можно открывать и читать файлы *.ttfr:
undefined
app:instance001> flightrec = require('flightrec')
: –-
app:instance001> flightrec_file = flightrec.open('var/lib/instance001/20231225T085435.ttfr')
: –-
app:instance001> flightrec_file
: –-
-
sections: &0
requests:
: size: 10485760
metrics:
: size: 368640
logs:
: size: 10485760
was_closed: false version: 0 pid: 1350
app:instance001> for i, r in flightrec_file.sections.logs:pairs() do record = r; break end
: –-
app:instance001> record
: –-
- level: INFO
: fiber_name: interactive fiber_id: 103 cord_name: main file: ./src/box/flightrec.c time: 2023-12-25 08:50:12.275 message: 'Flight recorder: configuration has been done' line: 727
app:instance001> flightrec_file:close()
: –-
В этом релизе немного изменен подход к поставке Tarantool конечным пользователям в виде пакетов DEB и RPM. В предыдущих версиях Tarantool собирался для наиболее популярных дистрибутивов Linux и их последних версий.
Начиная с этого релиза, поставляются только два набора пакетов DEB и RPM. Отличие в том, что эти пакеты содержат статически скомпилированный бинарный файл Tarantool. Благодаря такому подходу пакеты DEB и RPM можно устанавливать на любые дистрибутивы Linux, основанные на CentOS и Debian.
Для обеспечения работы Tarantool на широком спектре различных дистрибутивов и их версий пакеты RPM и DEB готовятся на CentOS 7 с glibc 2.17.
В предыдущих версиях Tarantool уже поддерживался тип varbinary для
хранения данных. Однако для работы с
полями базы данных типа varbinary требовались обходные пути, например
использование C для обработки таких данных.
В версию 3.0 добавлен новый модуль varbinary для работы с объектами
varbinary. Этот модуль реализует следующие функции:
-
varbinary.new()–- создает объект varbinary из обычной строки. -
varbinary.is()–- возвращает true, если аргумент является объектом varbinary. В примере ниже объект создается из строки:
local varbinary = require('varbinary')local bin = varbinary.new('Hello world!')
Теперь встроенные декодеры по умолчанию декодируют поля с бинарными данными в объект varbinary:
local varbinary = require('varbinary')local msgpack = require('msgpack')varbinary.is(msgpack.decode('\xC4\x02\xFF\xFE'))
–[[
: –-
- true ]] varbinary.is(yaml.decode('!!binary //4='))
–[[
: –-
- true ]]
Это также означает, что данные, хранящиеся в базе данных с типом поля
varbinary, теперь возвращаются в Lua не как обычная строка, а как
объект varbinary.
Можно вернуться к старому поведению, переключив новый параметр
binary_data_decoding compat, так как это изменение
может нарушить обратную совместимость:
compat:binary_data_decoding: old
Теперь при определении формата спейса можно задавать
значения по умолчанию для конкретных полей. В этом
примере поля isbn и title имеют указанные значения по умолчанию:
box.schema.space.create('books')box.space.books:format({{ name = 'id', type = 'unsigned' },{ name = 'isbn', type = 'string', default = '9990000000000' },{ name = 'title', type = 'string', default = 'New awesome book' },{ name = 'year_of_publication', type = 'unsigned', default = 2023 }})box.space.books:create_index('primary', { parts = { 'isbn' } })
Если вставить кортеж с недостающими полями, будут подставлены значения по умолчанию:
undefined
app:instance001> box.space.books:insert({ 1000, nil, nil, nil })
: –-
- [1000, '9990000000000', 'New awesome book', 2023]
Можно также задать пользовательскую логику для генерации значения по
умолчанию. Для этого создайте функцию с помощью
box.schema.func.create:
box.schema.func.create('current_year', {language = 'Lua',body = "function() return require('datetime').now().year end"})
Затем укажите имя функции в параметре default_func при определении
формата спейса:
box.space.books:format({-- ... --{ name = 'year_of_publication', type = 'unsigned', default_func = 'current_year' }})
Подробнее см. в index-defaults.
В версии 3.0 API для создания триггеров полностью
переработан. Добавлен новый модуль trigger, с помощью которого можно
задавать обработчики как для предопределенных, так и для
пользовательских событий.
Для создания триггера необходимо:
- Указать имя события, с которым будет связан триггер.
- Задать имя триггера.
3) Предоставить функцию-обработчик триггера. В примере ниже показано,
как подписаться на изменения в спейсе books:
local trigger = require('trigger')trigger.set('box.space.books.on_replace', -- event name'some-custom-trigger', -- trigger namefunction(...)-- trigger handlerend)
В релизе 2.11 добавлены следующие возможности:
-
Представления чтения –- снимки в памяти всей базы данных, на которые не влияют последующие изменения данных.
-
Пагинация для получения данных порциями. В релизе 3.0 объект представления чтения поддерживает аргументы
afterиfetch_posдля методовselectиpairs:
-- Select first 3 tuples and fetch a last tuple's position --
app:instance001> result, position = read_view1.space.bands:select({}, { limit = 3, fetch_pos = true })
: –-
app:instance001> result
: –-
-
- [1, 'Roxette', 1986]
- [2, 'Scorpions', 1965]
- [3, 'Ace of Base', 1987]
app:instance001> position
: –-
- kQM
– Затем эту позицию можно передать в качестве параметра 'after' –
app:instance001> read_view1.space.bands:select({}, { limit = 3, after = position })
: –-
-
- [4, 'The Beatles', 1960]
- [5, 'Pink Floyd', 1965]
- [6, 'The Rolling Stones', 1962]
Начиная с версии 3.0 протокол IPROTO расширен поддержкой отправки имен полей кортежа в ответах IPROTO_CALL и других ответах IPROTO. Это упрощает разработку коннекторов Tarantool, а также работу с кортежами, полученными в результате удаленных вызовов процедур или от роутеров.
Вернуться к прежнему поведению можно, переключив параметр
box_tuple_extension модуля compat:
compat:box_tuple_extension: old
Начиная с версии 3.0 имена в SQL, например, имена
таблиц, колонок или ограничений, чувствительны к регистру. До версии
3.0 приведенный ниже запрос создавал таблицу MYTABLE:
CREATE TABLE MyTable (i INT PRIMARY KEY);
Чтобы создать таблицу MyTable, имя нужно было заключить в двойные
кавычки:
CREATE TABLE "MyTable" (i INT PRIMARY KEY);
Начиная с версии 3.0 имена чувствительны к регистру, и двойные кавычки больше не требуются:
CREATE TABLE MyTable (i INT PRIMARY KEY);
Для обратной совместимости в новой версии также поддерживается повторный
поиск по имени в верхнем регистре. Это означает, что приведенный ниже
запрос сначала пытается найти таблицу MyTable, а затем MYTABLE:
SELECT * FROM MyTable;
В релиз 3.0 включено исправление проблемы LuaJIT
gh-562, связанной с
невозможностью обработки внутренних ошибок компилятора при выполнении
трассировок с помощью pcall. Примеры таких ошибок:
-
Ошибка
Out of memoryможет возникать для запросовselect, возвращающих большой объем данных. -
Ошибка
Table overflowвозникает при превышении максимального количества ключей в таблице. Приведенный ниже скрипт пытается заполнить Lua-таблицу большим количеством ключей:
local function memory_payload()local t = {}for i = 1, 1e10 dot[ffi.new('uint64_t')] = iendendlocal res, err = pcall(memory_payload)print(res, err)
В предыдущей версии Tarantool с 32-битным Lua GC этот скрипт вызывает
следующую ошибку, несмотря на использование pcall:
PANIC: unprotected error in call to Lua API (not enough memory)
В Tarantool с 64-битным Lua GC этот скрипт вызывает ошибку
Table overflow:
PANIC: unprotected error in call to Lua API (table overflow)
Начиная с версии 3.0 эти ошибки обрабатываются корректно со следующими результатами:
false not enough memory -- 32-bit Lua GCfalse table overflow -- 64-bit Lua GC
В результате в Tarantool 3.0 повышается стабильность работы в случаях, когда пользовательские скрипты содержат ошибочный код.