CRUD 0.11.0 для Tarantool

от автора

Оригинальный арт: @darkslog_0log
Оригинальный арт: @darkslog_0log

Неделю назад вышла новая версия модуля CRUD для Tarantool. В 0.11.0 появилось множество нововведений, просьбы о которых поступали от наших пользователей. Что изменилось, как этим пользоваться и кому это может быть полезно? Расскажем обо всём.

Tarantool — это платформа in-memory вычислений с гибкой схемой данных, функциональность которой расширяется с помощью модулей. Одними из самых популярных являются vshard, предназначенный для распределённого хранения данных, и cartridge, который организует работу с кластером Tarantool. CRUD также можно считать членом этого семейства: он предназначен для написания запросов при работе с распределёнными данными. Мы в Tarantool активно используем его при разработке готовых решений и нередко упоминаем в статьях (например, здесь и здесь).

Статистика

Оригинал: https://xkcd.ru/605/
Оригинал: https://xkcd.ru/605/

В 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

Фрагмент картины Б.М. Кустодиева «Купец, считающий деньги» (1918 г.)
Фрагмент картины Б.М. Кустодиева «Купец, считающий деньги» (1918 г.)

В 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-чате.


ссылка на оригинал статьи https://habr.com/ru/company/vk/blog/663496/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *