Неделю назад вышла новая версия модуля CRUD для Tarantool. В 0.11.0 появилось множество нововведений, просьбы о которых поступали от наших пользователей. Что изменилось, как этим пользоваться и кому это может быть полезно? Расскажем обо всём.
Tarantool — это платформа in-memory вычислений с гибкой схемой данных, функциональность которой расширяется с помощью модулей. Одними из самых популярных являются vshard, предназначенный для распределённого хранения данных, и cartridge, который организует работу с кластером Tarantool. CRUD также можно считать членом этого семейства: он предназначен для написания запросов при работе с распределёнными данными. Мы в Tarantool активно используем его при разработке готовых решений и нередко упоминаем в статьях (например, здесь и здесь).
Статистика
В CRUD 0.11.0 появилась возможность собирать статистику о запросах. Чтобы включить её, вызовите
crud.cfg{ stats = true }
А чтобы собирать статистику постоянно, добавьте вызов в init-код вашего роутера.
local crud = require('crud')
local function init(opts)
crud.cfg{ stats = true }
-- Place your code here.
end
-- Place your code here.
return {
dependencies = {
'cartridge.roles.metrics',
'cartridge.roles.crud-router',
},
init = init,
-- Place your role methods here.
}
Сбор статистики можно включить и на ограниченный период времени: вызовите код в интерактивном режиме на нужном роутере, а после выключите с помощью симметричного вызова.
crud.cfg{ stats = false }
Получить статистику можно с помощью команды
crud.stats()
---
- spaces:
my_space:
insert:
ok:
latency: 0.002
count: 19800
time: 39.6
error:
latency: 0.000001
count: 4
time: 0.000004
Информация о вызовах разделяется по спейсам, типу запроса и результату его выполнения. count
отображает количество запросов, time
— суммарную длительность их выполнения, latency
— длительность выполнения одного запроса.
Можно получить информацию о конкретном спейсе.
crud.stats('my_space')
---
- insert:
ok:
latency: 0.002
count: 19800
time: 39.6
error:
latency: 0.000001
count: 4
time: 0.000004
При необходимости можно сбросить счётчики.
crud.reset_stats()
Кроме стандартного набора показателей, из которого можно сделать вывод о производительности вашего приложения, для запросов select
/pairs
(они оба включены в секцию статистики select
) собирается дополнительная диагностическая информация.
crud.stats('my_space')
---
- select:
ok:
latency: 0.015
count: 3120
time: 51.2
error:
latency: 0.0001
count: 3
time: 0.0003
details:
map_reduces: 40
tuples_fetched: 10500
tuples_lookup: 238000
...
tuples_fetched
— это суммарное количество записей в ответах на запросы на чтение;tuples_lookup
— количество записей, которые были просмотрены при формировании ответов;map_reduces
— количество запросов, которые привели к обходу всего кластера.
С её помощью можно отлавливать на конкретном спейсе неэффективные или «тяжёлые» запросы, делать выводы о необходимости добавления индекса в схему или изменении ключа шардирования. Одна из главных причин появления детализированной статистики — ситуации, в которых в условие на ключ по ошибке попадает nil
. Это может привести к падению процесса или значительному замедлению работы. Кстати, недавно для select{nil}
появилось предупреждение и на уровне самого Tarantool (см. issue в tarantool/tarantool).
Получать статистику можно не только в коде или консоли: эта функциональность интегрирована с metrics — стандартным модулем для работы с метриками в Tarantool. CRUD по умолчанию использует коллекторы metrics для хранения статистики, если в приложении установлен модуль нужной версии. При необходимости можно переключать способ хранения самостоятельно:
-- Store in Lua tables.
crud.cfg{ stats = true, stats_driver = 'local' }
-- Store in metrics registry, stats could be
-- exported to the Prometheus/InfluxDB/Graphite.
crud.cfg{ stats = true, stats_driver = 'metrics' }
Подробнее про мониторинг Tarantool с помощью metrics можно узнать в этой статье.
Накладные расходы на сбор статистики — порядка 3-10 % в случае драйвера local
и 5-15 % в случае драйвера metrics
в зависимости от запроса. При использовании квантилей в худшем случае нагрузка вырастет на 20 %.
В ближайшее время панели для статистики CRUD появятся в стандартном дашборде Grafana для Tarantool.
crud.count
В CRUD 0.11.0 также появился новый метод: crud.count
. Он позволяет получить информацию о количестве записей в кластере, удовлетворяющих заданным условиям (семантика аналогична select
/pairs
).
crud.count('customers', {{'<=', 'age', 35}, {'==', 'department', 'RnD'}})
---
- 11
...
Не стоит его путать с crud.len
, который возвращает общее количество всех записей в спейсе. Метод crud.count
больше похож на обычный crud.select
, но работает значительно быстрее, потому что ему не нужно возвращать данные.
Запрос на этот метод возник при разработке OPM в рамках одного из наших проектов, но он может быть полезен при реализации любой другой бизнес-логики.
Шардирование
Начиная с CRUD 0.10.0 пользователи могут конфигурировать условия распределения записей по кластеру. Версия 0.11.0 значительно расширяет эти возможности и исправляет некоторые серьёзные проблемы. Если вы уже использовали ключи шардирования в CRUD 0.10.0, то настоятельно рекомендуем обновиться.
Шардирование в приложениях на Tarantool Cartridge конфигурируется с помощью модуля DDL.
ddl_schema.lua
local ddl = require('ddl')
local schema = {
spaces = {
account = {
engine = 'memtx',
is_local = false,
temporary = false,
format = {
{name = 'account_id', is_nullable = false, type = 'unsigned'},
{name = 'customer_id', is_nullable = false, type = 'unsigned'},
{name = 'bucket_id', is_nullable = false, type = 'unsigned'},
{name = 'balance', is_nullable = false, type = 'string'},
{name = 'name', is_nullable = false, type = 'string'},
},
indexes = {{
name = 'account_id',
type = 'TREE',
unique = true,
parts = {
{path = 'account_id', is_nullable = false, type = 'unsigned'}
}
}, {
name = 'customer_id',
type = 'TREE',
unique = false,
parts = {
{path = 'customer_id', is_nullable = false, type = 'unsigned'}
}
}, {
name = 'bucket_id',
type = 'TREE',
unique = false,
parts = {
{path = 'bucket_id', is_nullable = false, type = 'unsigned'}
}
}},
sharding_key = {'customer_id'},
sharding_func = 'vshard.router.bucket_id_mpcrc32',
}
}
}
local _, err = ddl.set_schema(schema)
assert(err == nil)
В CRUD 0.11.0 появилась поддержка функций шардирования. Просто задайте их в схеме DDL и модуль CRUD автоматически подтянет всю необходимую информацию для запросов. В качестве функции шардирования можно использовать как имя уже существующей функции, так и её Lua-код.
schema.spaces.account.sharding_func = 'my_module.my_function'
schema.spaces.customers.sharding_func = {
body = [[[
function(key)
local vshard = require('vshard')
return vshard.router.bucket_id_mpcrc32(key)
end
]]]
}
local _, err = ddl.set_schema(schema)
assert(err == nil)
Вместо DDL можно использовать его элементы — служебные спейсы _ddl_sharding_key
и _ddl_sharding_func
. Информации из них будет достаточно для работы CRUD.
Одна из самых популярных ситуаций для задания функции шардирования — использование более стабильного vshard.router.bucket_id_mpcrc32
вместо стандартного vshard.router.bucket_id_strcrc32
. Имейте в виду, что на данный момент есть некоторые ограничения по их использованию в DDL.
Также в CRUD 0.11.0 появился механизм автоматической перезагрузки схемы шардирования. Прежде её актуальность необходимо было поддерживать вручную, а использование устаревшей схемы с большой вероятностью приводило к неконсистентности данных. Теперь при каждом запросе валидируется актуальность схемы; при получении соответствующей ошибки метаданные на роутере обновляются, а запрос отправляется в обработку повторно.
Кроме того
Исправлен баг, при котором после запроса изменялось содержимое входных аргументов-таблиц.
Починена обработка ошибок, полученных от хранилища в запросах select/pairs.
Оптимизирован запрос на чтение в ситуации с заранее заданными условиями шардирования.
Добавлены сценарии для нагрузочного тестирования, в том числе сравнение с модулем vshard.
Вместо заключения
CRUD — один из наиболее популярных модулей для Tarantool. Все крупные нововведения, появившиеся в 0.11.0, создавались по запросам наших клиентов: как пользователей из внутренних отделов, так и внешних разработчиков из других команд и компаний. Поэтому если вам есть, что нам сказать — мы всегда открыты.
Скачать Tarantool можно на официальном сайте, а получить помощь — в Telegram-чате.