Два года назад все началось с первого коммита и туманного понимания, что мы вообще хотим сделать. Сегодня — два мажорных релиза, собственный модуль миграций, документация, тренинги и пользователи, которые безболезненно перешли на новую версию по нашим инструкциям. Но путь от «кучи кода для внутреннего использования» до полноценной коробочной In-memory-базы оказался совсем не прямым. 

Меня зовут Александр Кленов, я тимлид разработки Tarantool DB в команде Tarantool. Я расскажу историю о том, как мы брали зрелый, но очень гибкий Tarantool Enterprise и превращали его в решение, которое можно установить из коробки.

Начало: проблемы, из которых все выросло

Tarantool Enterprise — мощная, гибкая, кластерная In-memory-база данных и Application Server. Но эта же гибкость была ее слабым местом: пользователи часто шли в неподходящие сценарии и получали неожиданные результаты.

Изначально мы даже не думали о коробке. Первая цель была скромнее: сделать типовой шаблон приложения, чтобы снизить порог входа и избежать неправильных паттернов использования. Так появился Tarantool KVEE 0.1.0.

Проблема №1: однопоточность и LuaJIT

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

В итоге Tarantool — это как швейцарский нож: однопоточная база + встроенный язык, на котором можно написать что угодно. И пользователи действительно писали что угодно. Часто прямо в Tarantool пихали сложную бизнес-логику. На одном потоке это приводило к низкой производительности.

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

Проблема №2: экспертиза и Time-to-market

Когда в Tarantool Enterprise внутрь приложения добавляют бизнес-логику, без глубокой экспертизы не обойтись. Типичный цикл разработки выглядит так:

  1. Затянуть Tarantool SDK в свой контур.

  2. Дописать/переписать логику.

  3. Протестировать, часто в несколько этапов.

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

  5. Деплой новой версии приложения (сине-зеленый, с технологическим окном или еще какой).

  6. Какое-то время пристально наблюдать за метриками.

  7. Если нужно что-то доработать, перейти к пункту 2.

Причем деплой должен делать тот же специалист, который писал доработки, иначе высок риск проблем.

Минусы такого подхода:

  • высокий TTM;

  • необходимость выращивать редких специалистов;

  • сложная поддержка, ведь каждое падение — уникальный случай.

Я сам работал в таких проектах: тяжело совмещать роль разработчика, девопса и саппорта в одном лице. Нужно было придумать, как эти роли развести.

Проблема №3: архитектурные ограничения Tarantool 2

В Tarantool 2 бинарь умеет собирать только репликасет — группу серверов с репликацией. Про шардинг он ничего не знает: чтобы распределить данные, нужно использовать библиотеку vshard.

Еще в «двойке» нет встроенного кластерного конфига, админки и некоторых инструментов, которые нужны в продакшене. Все это дает фреймворк Cartridge, также известный как «Карж».

Cartridge сильно расширяет возможности Tarantool, и на нем построено целое поколение приложений, в том числе Tarantool Data Grid. Но у него есть и ограничения. Например, Raft-фейловер в продакшене переключается примерно в 10 раз медленнее, чем фейловер на координаторах.

Причина в том, что в Tarantool Enterprise изначально фейловера не было, а первый появился именно в Cartridge — как Lua-код, который сам решает, когда и как переключать мастера. Новый же Raft — это часть бинаря и работает иначе: решение о мастере принимает сама СУБД, без задержек на синхронизацию Lua-слоя.

Кроме того, Cartridge хранит конфигурацию на всех узлах кластера и обновляет ее через двухфазный коммит. Это порождает проблемы при нестабильной сети, а на больших кластерах (>500 инстансов) становится болью.

Что изменил Tarantool 3

Tarantool 3 избавился от перечисленных выше ограничений:

  • конфигурация хранится в централизованном кластере с синхронной репликацией;

  • шардинг, кластерный конфиг и оба фейловера (Raft и координаторный) — это часть бинаря;

  • появился отдельный инструмент для управления кластерами — TCM.

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

Но есть проблема: Tarantool 2 и Tarantool 3 сильно различаются внутри и миграция между ними — нетривиальная задача. Именно на стыке этих версий мы и начали думать о коробочном решении.

Как мы взяли Tarantool Enterprise и превратили в коробку

К этому моменту у нас было несколько важных наблюдений:

  • Tarantool слишком гибкий — пользователи легко заходят в «опасные» сценарии.

  • В Tarantool 2 и 3 есть существенные архитектурные отличия — миграция между ними требует много работы и экспертизы.

  • Эксплуатация приложений на Tarantool часто завязана на уникальную бизнес-логику, что усложняет поддержку и увеличивает TTM.

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

  • убрать лишние варианты использования;

  • стандартизировать конфигурации;

  • заранее заложить лучшие практики.

Так и родилась идея коробки.

Ограничения как фича

Мы решили, что продуктом должны управлять две разные роли.

DevOps-команда. Устанавливает и обновляет конкретную версию базы данных. Это всегда единый артефакт со своим набором файлов, без пользовательского кода. Обновления редкие и контролируемые. По-хорошему, у девопсов должно быть ровно столько прав, чтобы просто обновить продукт.

Разработчики. Используют базу, но не занимаются деплоем и не могут подмешать свой код в артефакт. Весь их контакт с системой — через запросы к БД.

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

Механизм миграций

Все изменения теперь проходят через единый механизм миграций, который умеет:

  • создавать и изменять спейсы (таблицы), индексы и другие объекты БД;

  • добавлять и обновлять хранимые процедуры;

  • выполнять миграции данных;

  • вести историю изменений и автоматически применять их на новых инстансах или тех, что подняты из бэкапа.

Планы на будущее — сделать миграцию атомарной операцией. Это избавит от промежуточных состояний при сбое и еще сильнее упростит жизнь разработчикам и девопсам.

Что мы убрали, а что оставили

Мы сознательно вырезали все, что усложняло продукт или ухудшало пользовательский опыт:

  • шардинг-группы — аналогичный эффект проще достигнуть с помощью отдельных кластеров, а администрирование при этом становится понятнее;

  • GraphQL — красивый, но тяжелый в поддержке слой, который редко нужен именно внутри базы;

  • веб-API — мы решили, что интеграции должны жить снаружи, а не нагружать саму БД;

  • Kafka-коннектор и другие коннекторы — опыт показал, что их лучше разворачивать и настраивать отдельно, чтобы не мешать работе кластера;

  • и прочее — мы оставили продукт максимально сфокусированным, а все лишнее вынесли за его пределы.

Идея простая: чем меньше вариантов «пострелять себе в ногу», тем быстрее и безопаснее внедряется продукт.

Ограничения — это хорошо, но ядро должно быть полезным. Поэтому кроме механизма миграций мы:

  • оставили шардинг;

  • оставили модуль CRUD — он позволяет выполнять простые CRUD-запросы к кластеру так, будто это один инстанс;

  • оставили Expirationd — модуль для автоматического удаления или переноса устаревших данных;

  • добавили модуль трассировки и инструмент выявления медленных запросов;

  • добавили коннектор к Tarantool Clusters Federation — для синхронизации данных между кластерами;

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

Продолжаем понижать порог входа — документация

Минимум фич дал нам возможность сделать продукту качественную документацию. Критерий был простой: все задачи должен суметь выполнить человек без опыта работы с Tarantool, опираясь только на документацию.

Начали мы с тестового стенда. Хотелось, чтобы любой мог выполнить одну команду, поднять полноценный кластер локально и поэкспериментировать. Мы сделали стенд на Docker Compose и начали поставлять продукт не только как архив для разворачивания, но и как Docker-образ.

Это было отличным решением... пока мы не пошли на сертификацию во ФСТЭК. Там Docker не используют. Но на тот момент стенд отлично работал, и на его базе мы сделали десятки примеров:

  • как поднять все на одном инстансе;

  • как работать с бинарными данными;

  • как добавить свои метрики;

  • как работать со словарями;

  • и многое другое.

Мы также сделали упор на два коннектора — Go и Java — и написали несколько рабочих примеров для каждого.

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

Мы сделали поставку документации в виде архива. А также синхронизировали ее с tarantool.io.

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

  • скругляли острые углы;

  • ловили баги;

  • добавили набор скриптов для настройки топологии кластера локально, загрузки Java-коннектора и применения миграций;

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

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

Создание продуктового цикла

Цель — сделать так, чтобы релизы Tarantool DB были предсказуемыми, качественными, а обновления для пользователей проходили безболезненно.

Процессы

Мы выстроили понятную цепочку:

  1. Планирование — совместно с PM определяем, какие фичи пойдут в релиз, и фиксируем объем.

  2. Разработка — ведем параллельно по компонентам, но с учетом общего дедлайна.

  3. Выпуск релиз-кандидата.

  4. Предрелизное тестирование — интеграционное и нагрузочное тестирование продукта. Стабилизация продукта.

  5. Релиз «со всеми пирогами» — Changelog, инструкция по обновлению, артефакты, публикация.

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

От тестов компонентов к тестам продукта

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

Для нагрузочного тестирования выбрали K6, доработали его под наши нужды и получили собственный инструмент — K6-Tarantool. Подробнее об этом — в докладе на Moscow QA.

Железо против виртуалок

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

Что получилось и что мы планируем

В итоге у нас получились следующие результаты:

  • план из ~90 параметрических тестовых сценариев;

  • интеграция с Allure;

  • QA-регламенты: приоритизация багов, фокус на воспроизводимость, скорость фиксов.

А вот что в планах:

  • ночные тесты — автоматическая сборка из мастер-веток всех компонентов и полное тестирование каждую ночь. Это позволит поймать баги заранее, а не на релизе (уже несколько раз наступали на эти грабли);

  • релизный календарь — пока в планах;

  • автоматическая отчетность о тестировании — вроде не так сложно, но руки пока не дошли.

Tarantool 3 и путаница с версиями

7 мая 2024 года мы выпустили Tarantool DB 1.0 — продукт на базе платформы Tarantool Enterprise 2.11. Но в тот момент уже готовился релиз Tarantool Enterprise 3 — были Dev-сборки, и мы наглядно видели, насколько сильно версия 3 отличается от версии 2.

Для нас это означало, что почти все придется сделать заново:

  • новый состав модулей;

  • другое взаимодействие с ними;

  • новый механизм работы с конфигурациями;

  • новые примеры и новая документация;

  • новый план тестирования;

  • и много других изменений.

Так началась разработка Tarantool DB 2.x — уже на базе Tarantool Enterprise 3.

Сложность была в том, что первую версию нужно было продолжать поддерживать.

Плюс после перестановок в командах к нам на поддержку пришли еще и новые компоненты:

  • Cartridge;

  • CRUD;

  • Expirationd;

  • Metrics;

  • Membership;

  • и другие.

Работы было много.

Как организовали разработку

Мы выбирали между двумя подходами: завести отдельный репозиторий или сделать вторую мастер-ветку.

Остановились на второй мастер-ветке:

  • все релизы в одном месте;

  • можно копировать коммиты, подходящие обеим веткам;

  • общая история и контекст.

Сейчас могу сказать: нам норм.

О чем TDB2

Мы хотели, чтобы пользователи, которые перешли с кастомного приложения на Tarantool DB 1.x, могли из коробки мигрировать и на Tarantool DB 2.x, построенный на базе Tarantool Enterprise 3.x.

Чувствуете путаницу с версиями? Вроде оно так закономерно сложилось, и внутри компании был небольшой холивар по поводу переименования продукта. Был вариант называть Tarantool DB 25.1.0 (год.квартал.патч). Был вариант перейти на имена. Но в итоге решили оставить как есть и выпустить Tarantool DB 3.0 с новыми фичами на базе Tarantool Enterprise 3.x.

Кстати, мы его готовим к началу октября. Там будет поддержка хранения данных на диске и архивирование/охлаждение на диск.

Вообще, Vinyl-движок в Tarantool давно есть, но у нас он появится только в следующей версии. Как бы то ни было, 19 сентября 2024 года мы выпустили релиз Tarantool DB 2.x.

Тренинг

Позднее мы взялись за подготовку нового тренинга для разработчиков по Tarantool DB 2.x. К работе подключились коллеги из разных команд.

Раньше у нас уже был хороший тренинг по Tarantool, но в TDB многие вещи спрятаны под капот — разработчику не нужно вникать в нюансы настройки и обслуживания. Поэтому мы сократили программу старого тренинга, убрав лишнюю техническую «тяжелую» часть, а еще добавили материал на базе примеров из нашей документации.

Мы подготовили лонгриды, записали видео и придумали тесты для закрепления материала.

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

Итоги за два года

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

  • два мажорных релиза — Tarantool DB 1.x и Tarantool DB 2.x;

  • выстроенные процессы планирования, разработки, тестирования и релизов;

  • собственный механизм миграций и набор модулей, которые решают проблемы производительности, TTM и сложной поддержки;

  • четкое разграничение ролей: девопсы администрируют продукт, разработчики пишут логику вне БД;

  • качественная документация, примеры, тренинг для разработчиков;

  • поддержка и развитие ключевых компонентов Cartridge-экосистемы.

Многие из проблем, с которых мы начинали («слишком гибкий продукт», высокая планка входа, сложный деплой и долгий TTM), мы смогли решить за счет ограничений «как фичи», унифицированных сценариев и автоматизации.

За эти два года мы убедились: главное — не просто писать код, а делать продукт, которым удобно пользоваться и который можно легко внедрить. И кажется, нам это удается.


Вступайте в чат сообщества Tarantool и подписывайтесь на наш канал в Telegram.

Комментарии (0)