Pull to refresh
VK
Building the Internet

CRUD 0.11.0 для Tarantool

Reading time6 min
Views2.5K
Оригинальный арт: @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 можно узнать в этой статье.

По умолчанию latency отображает среднее время выполнения запроса, но при использовании драйвера metrics их можно заменить на 99-е квантили с устареванием. Чтобы включить их, вызовите следующую команду:

crud.cfg{ stats_quantiles = true }

Накладные расходы на сбор статистики — порядка 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-чате.

Tags:
Hubs:
+41
Comments1

Articles

Information

Website
vk.com
Registered
Founded
Employees
5,001–10,000 employees
Location
Россия
Representative
Миша Берггрен