10 возможностей современного Tarantool, о которых вы могли не знать

от автора

В прошлом году Tarantool исполнилось 15 лет. Он прошел долгий путь от обычного кэша до платформы управления данными с десятками разных внутренних продуктов и расширений. Такое обилие инструментов создает множество возможностей — и в этой статье мы расскажем о десяти, о которых многие забывают или попросту не знают.

Кластерный конфиг

Одно из главных нововведений в последней мажорной версии Tarantool — единая точка конфигурации.

Настраивать Tarantool через box.cfg слишком сложно? Неудобно хранить настройки в Lua-файлах или передавать их через env? В Tarantool 3.0 появилась возможность создать общий кластерный конфиг для всех узлов Tarantool.

Чтобы запустить Tarantool, вам понадобится конфиг следующего вида:

# объявляем пользователей в кластере credentials:   users:     guest:       roles: [super]  # объявляем настройки для подключения к узлу iproto:   listen:   - uri: 'unix/:./{{ instance_name }}.iproto'  # описываем топологию кластера и настройки всех узлов groups:   group-001:     replicasets:       replicaset-001:         instances:           instance-001: {}

Потом понадобится выполнить следующую команду:

tarantool --config config.yaml --name instance-001

Что можно указать в конфигурационном файле:

  • все параметры для настройки Tarantool (то, что раньше указывалось в box.cfg);

  • топологию, в том числе и для шардированного кластера;

  • параметры и роли приложений (похожим образом, как в картридже);

  • параметры фейловера — в скором времени мы добавим их еще больше.

В Tarantool Enterprise конфиг можно хранить в etcd, и обновления будут загружаться в Tarantool автоматически.

Больше примеров лежит в гитхабе.

Персистентность и WAL

Многие все еще думают о Tarantool как о простом кэше, который нельзя использовать для хранения важных данных. Когда-то это было так, но все давно изменилось. Персистентность в Tarantool включена по умолчанию: он всегда сохраняет данные на диске, перед тем как отдать пользователю подтверждение записи.

Но вы всегда можете превратить Tarantool в кэш всего одной настройкой:

box.cfg{wal_mode = 'none'} -- делаем из Tarantool кэш

А для автоматического удаления устаревших данных можно использовать наш модуль expirationd:

local expirationd = require("expirationd")  function is_expired(args, tuple)   return true end  function delete_tuple(space, args, tuple)   box.space[space]:delete{tuple[1]} end  expirationd.start(job_name, space.id, is_expired, {     process_expired_tuple = delete_tuple,     args = nil,     tuples_per_iteration = 50,     full_scan_time = 3600 })

Синхра и рафт

Вам нужны дополнительные гарантии при записи? Вас пугает асинхронная репликация? Попробуйте синхру! А если вы хотите автоматическое переключение лидера, не забудьте настроить рафт.

Мы писали о рафте и синхре на Хабре много раз, но, если вы пропустили, рекомендуем ознакомиться подробнее в предыдущих статьях: 

Как пользоваться синхрой и рафтом?

Первый узел:

# объявляем пользователей в кластере credentials:   users:     admin:       password: 'passwd'       roles: [super]  # объявляем настройки для общения инстансов между собой # (их также можно задавать на уровне узлов, репликасетов и групп) iproto:   listen:   - uri: 'unix/:./{{ instance_name }}.iproto'   advertise:     peer:       login: 'admin'  # включаем автоматический фейловер на базе Raft replication:   failover: election  # описываем топологию кластера и настройки всех узлов groups:   group-001:     replicasets:       replicaset-001:         instances:           instance-001: {}           instance-002: {}           instance-003: {}

Запускаем кластер:

tarantool --config config.yaml --name instance-001 tarantool --config config.yaml --name instance-002 tarantool --config config.yaml --name instance-003

Снова на первом узле:

box.ctl.promote()  box.schema.space.create('employees', {is_sync = true}) box.space.customers:format({     {name = 'id', type = 'integer'},     {name = 'name', type = 'string'},     {name = 'salary', type = 'integer'},     {name = 'department', type = 'string'}, }) box.space.employees:create_index('pk', {parts = {'id'})      -- теперь можно работать с данными:      box.space.customers:insert{...}

Хранение на диске с Vinyl

Tarantool, как и все современные базы данных, умеет сохранять данные на диске.

Процесс создания дискового спейса в Tarantool ничем не отличается от спейсов в памяти:

-- создаем спейс с дисковым движком box.schema.create_space('former_employees', {engine = 'vinyl'})  box.space.former_employees:format({     {name = 'id', type = 'integer'},     {name = 'name', type = 'string'},     {name = 'salary', type = 'integer'},     {name = 'department', type = 'string'},     {name = 'end_date', type = 'datetime'}, })  box.space.former_employees:create_index('pk', {parts = {'employee_id'}})   -- переносим устаревшие данные в холодное хранилище  box.begin() for key, tuple in box.space.employees.index.end_date:pairs(now, {iterator = 'LE'}) do     box.space.former_employees:insert(tuple)     box.space.employees:delete(key) end box.commit()

При работе с vinyl всегда стоит помнить о том, что Tarantool в первую очередь in-memory-технология. У дискового движка есть серьезные ограничения — например, мы не рекомендуем создавать больше одного индекса для таких данных и делать апдейты в сохраненных данных.

Подробнее о vinyl можно прочитать в статье на Хабре.

Констрейнты и внешние ключи

Хотите, чтобы было как в SQL? Попробуйте констрейнты и внешние ключи.

-- Define a tuple constraint function -- box.schema.func.create('check_dates', {     language = 'LUA',     is_deterministic = true,     body = [[function(t)          if t.end_date then              return t.start_date < t.end_date         end         return     end]] })  -- Define a field constraint function -- box.schema.func.create('check_salary', {     language = 'LUA',     is_deterministic = true,     body = 'function(f) return f > 0 and f < 10^9 end' })  box.schema.space.create('departments') box.space.deparments:format({     {name = 'id', type = 'string'},     {name = 'name', type = 'string'},     {name = 'manager', type = 'string'}, }) box.space.deparments:create_index('pk', {parts = {'id'}})   box.schema.space.create('employees', {constraint = 'check_dates'}) box.space.customers:format({     {name = 'id', type = 'integer'},     {name = 'name', type = 'string'},     {name = 'salary', type = 'integer', constraint = 'check_salary'},     {name = 'department', type = 'string', foreign_key = {space = 'departments', field = 'id'}},     {name = 'start_date', type = 'datetime'},     {name = 'end_date', type = 'datetime', is_nullable = true}, }) box.space.employees:create_index('pk', {parts = {'id'})

Помните, что для некоторых изменений формата вам потребуется произвести дополнительные миграции.

Транзакции, стримы и отменяемые запросы

Вы привыкли, что в транзакциях в Tarantool нельзя идлить? Привыкли к тому, что все транзакции по умолчанию serializable? Хотите более гибкого контроля над транзакциями? Используйте MVCC-движок:

local fiber = require('fiber') local log = require('log') box.cfg{memtx_use_mvcc_engine = true} box.schema.create_space('test') box.space.test:format{{name='first', type='string'}, {name='second', type='integer'}} box.space.test:create_index('pk', {parts = {'first'}})  box.space.test:put{'value', 1} fiber.new(function() v1 = box.space.test:select() end) -- этот код исполнится после йилда box.atomic(function()     box.space.test:put{'value', 2}     fiber.yield()     v2 = box.space.test:select()     box.space.test:put{'value', 3} end) v3 = box.space.test:select() log.info(v1, v2, v3)   --- # это значение в момент йилда в транзакции,  # транзакция не завершена, поэтому мы получаем старое значение - - ['value', 1] # это значение, прочитанное в транзакции # в рамках самой транзакции эти данные уже существуют, поэтому здесь 2 - - ['value', 2] # это значение, полученное после завершения транзакции - - ['value', 3] ...

Вы также можете использовать интерактивные транзакции или выбирать время, через которое долгие запросы будут отменены:

fiber.set_max_slice{warn = 0.5, err = 1.0}

SQL

Вы страдаете от того, что нужно писать сложные запросы на Lua? Боитесь, что ваши аналитики не справятся с Tarantool? Напишите запросы на SQL! (Или прочитайте статью про сложные запросы в Tarantool).

Вот так можно создать таблицу и написать к ней запросы на SQL.

1. Для начала вам потребуется поменять язык в тарантульной консоли (если вы работаете через подключение к узлу) с помощью \set language sql или позвать команду box.execute и передать туда свой SQL-запрос.

Создаем таблицы:

CREATE TABLE employees ( ​​​    id INTEGER, ​​​    name STRING,  ​​​    salary INTEGER,  ​​​    department STRING,  ​​​    PRIMARY KEY (id) ​​​);  CREATE TABLE departments ( ​​​    id STRING, ​​​    manager STRING,  ​​​    PRIMARY KEY (id) ​​​);

2. Создаем индексы:

​​​CREATE INDEX salary ON employees (salary);

3. Вставляем данные:

​​​INSERT INTO departments VALUES ('Sales', 'Mighty Manager'); ​​​... ​​​INSERT INTO employees VALUES (1, 'John', 100000, 'Sales'); ​​​...

4. Пишем запросы:

​​​SET SESSION "sql_seq_scan" = true; ​​​ ​​​SELECT department, AVG(salary) ​​​FROM employees ​​​GROUP BY department;   ---    - metadata:      - name: department        type: string      - name: COLUMN_1        type: integer      rows:      - ['Sales', 100000]

5. Пишем джойны:

​​​SELECT employees.name, employees.salary, employees.department, department.manager  ​​​FROM employees JOIN departments ​​​ON (employees.department = departments.id); ​​​- metadata: ​​​  - name: name ​​​    type: string ​​​  - name: salary ​​​    type: integer ​​​  - name: department ​​​    type: string ​​​  - name: manager ​​​    type: string ​​​  rows: ​​​  - ['John', 100000, 'Sales', 'Mighty Manager']

Больше примеров —  в гайде по Tarantool.

И помните, что с любыми тарантульными спейсами можно работать как из Lua, так и из SQL, меняя подход в зависимости от задачи.

Шардирование

Шардирование — стандартный подход к масштабированию баз данных. В отличие от многих реляционных БД, в Tarantool шардирование давно стало стандартным модулем и поддерживается в конфиге. Все, что нужно сделать, — установить модуль vshard (tt rocks install vshard) и написать кластерный конфиг для Tarantool:

credentials:   users:     admin:       password: 'passwd'       roles: [super]  iproto:   listen:   - uri: 'unix/:./{{ instance_name }}.iproto'   advertise:     peer:       login: 'admin'     sharding:       login: 'admin'  sharding:   bucket_count: 10000    replication:   failover: election  groups:   storages:     sharding:       roles: [storage]     replicasets:       storages-001:         instances:           storage-001:             iproto:               listen:               - uri: 'localhost:3301'           storage-002:               iproto:               listen:               - uri: 'localhost:3302'       storages-002:         instances:           storage-003:                iproto:               listen:               - uri: 'localhost:3303'           storage-004:             iproto:               listen:               - uri: 'localhost:3304'   routers:     replicasets:       routers-001:         sharding:           roles: [router]         instances:           router-001:                iproto:               listen:               - uri: 'localhost:3300'   tt connect admin:passwd@localhost:3300

Чтобы начать работать с шардом, надо забутстрапить кластер:

vshard.router.bootstrap()

Теперь можно вставлять данные. На роутере:

vshard.router.callrw('box.space.test_space:insert', {...})

Хранение данных в различных парадигмах

Современный Tarantool позволяет вам применять различные парадигмы для работы с данными. Вот некоторые из примеров различных подходов, которые вы можете комбинировать в Tarantool:

  • key-value, document. Настройки формата в Tarantool позволяют вам не применять никакой формат вообще, что дает вам построить документное или kv-хранилище.

  • cache/master-storage. Tarantool можно использовать в качестве кэша (см. выше) или надежно хранить там важные данные.

  • in-memory/disk. Держите ваши спейсы в памяти, сгрузите все на диск или сделайте и то, и другое.

  • graph. Вы можете написать графовое хранилище самостоятельно, воспользовавшись нашими R-TREE-индексами, или взять готовый Tarantool Graph DB (Enterprise only).

  • column. Что? Хранение данных в колонках в памяти? В Tarantool? Да, с недавнего времени в Tarantool ЕЕ появился новый движок для хранения колонок.

  • queue. На Tarantool построено огромное количество очередей. Есть как бесплатные Tarantool queue и Sharded-queue, а есть Tarantool Queue Enterprise. Подробнее об очередях можно почитать в статье на Хабре.

  • cluster, multi-cluster. Tarantool отлично работает в кластерном режиме. Вы можете строить свои шардированные хранилища на базе опенсорсных vshard и Cartridge, а можете взять энтерпрайзные TDG или TDB. Также на Tarantool можно создать два кластера, которые полностью дублируют свои данные, с помощью Tarantool Clusters Federation.

Графический интерфейс

Управлять кластером всегда проще, когда можно взглянуть на страницу с обновляющимися онлайн статусами. Tarantool есть что вам предложить.

Grafana Dashboard

Тарантульный дашборд с метриками предоставляет все возможные параметры, за которыми можно следить. Все, что вам нужно знать о вашем тарантульном кластере, находится здесь: память, CPU и все возможные параметры рантайма в одном месте. Подробнее в статье на Хабре.

Если вы не любите настраивать кластеры через консоль или вам просто нужен удобный дашборд, где можно быстро узнать статус кластера и исправить известные проблемы в несколько кликов мышки, то вам следует попробовать один из наших продуктов с графическим интерфейсом.

Cartridge

Для Tarantool 1.10 / 2.х есть Cartridge — как создать первое приложение c его помощью, можно прочитать по ссылке. Помимо отображения информации о состоянии кластера, Cartridge занимается управлением кластерами и предоставляет свое API для различных настроек в кластере.

Tarantool Cluster Manager

Для новых кластеров на Tarantool 3.х есть Tarantool Cluster Manager (EE-only). В отличие от Cartridge, в TCM меньше управления кластером Tarantool (теперь кластерными вещами занимается сам Tarantool), но при этом больше возможностей для мониторинга и управления отдельными узлами, в том числе в разных кластерах.

Заключение

Это далеко не все возможности, которые может вам предложить современный Tarantool: достойны упоминания триггеры, кастомные аллокаторы, подключение к узлу из разных потоков и метрики в ядре по умолчанию. Но в одной статье все не перечислишь. Поэтому если вы пользуетесь Tarantool, следите за обновлениями. А если еще нет — обязательно попробуйте, у Tarantool наверняка есть что вам предложить.

Узнавайте о новых релизах, вебинарах и выходящих статьях в телеграм-канале Tarantool News.

Задать вопросы команде разработчиков про использование Tarantool можно в официальном канале сообщества.  

О принципах и примерах работы продуктов Tarantool читайте в блоге на сайте.


ссылка на оригинал статьи https://habr.com/ru/articles/843068/


Комментарии

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

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