Даже если вы никогда не слышали о Tarantool, вы наверняка им пользовались: видели баннеры, которые берут профили рекламы из Tarantool, заказывали еду, доставка которой обрабатывается Tarantool, заходили в онлайн-банк и видели историю трат, которую показывает Tarantool. Решение активно задействуют во многих отраслях и сценариях, а количество кейсов его успешного применения постоянно растет.
Но так было не всегда: за 15 лет Tarantool прошел большой путь, на котором были как успехи, так и подводные камни.
Меня зовут Сергей Останевич. Я руководитель разработки платформы Tarantool. В этой статье я расскажу о том, что сегодня представляет собой архитектура Tarantool, как она менялась и какие сейчас Tarantool дает преимущества для архитекторов и разработчиков.
Начало пути: платформа для разработчика
Tarantool был создан в 2008 году как внутренний проект для сети МойМир@Mail.ru. Обычные дисковые базы с потоком данных, в том числе пользовательских сессий и профилей, от всех сервисов Mail.ru уже к тому времени не справлялись. Поэтому мы решили строить Key-value-систему хранения.
Продукт разрабатывался и существовал в закрытом виде примерно два года — в 2010 году мы решили выкатить Tarantool в Open Source.
К моменту выхода Tarantool за рамки внутреннего решения (буквально на самой заре) мы уже успели в нем реализовать несколько критически важных решений.
-
Поддержка репликации для обеспечения сохранности данных даже в случае аварий. Tarantool умел писать данные с одного сервера на экземпляры-реплики на других серверах. Это давало гарантии, что данные будут доступны всегда и при любых сбоях. Вместе с тем переключение на реплику было несколько затруднено и сопряжено с определенными сложностями. При этом в контексте мультипоточной обработки у нас была принята «легковесная идеология» — у нас специальная парадигма файберов, которые подразумевают, что будет использоваться кооперативная мультизадачность. То есть программы должны писаться так, чтобы они позволяли явно уступать соседнему потоку.
-
Переход к LuaJIT как языку для хранимых процедур. Для написания клиентских хранимых процедур мы использовали интерпретатор Lua. Одновременно мы начали изучать LuaJIT, который был не только интерпретатором Lua, но и средой для компиляции «на лету» (Just-in-time). Причем решение в некоторых аспектах было даже лучше С-компиляторов. В результате мы перешли на LuaJIT.
-
Решение сделать Tarantool интерпретатором LuaJIT. После перехода на LuaJIT было принято решение сделать Tarantool LuaJIT-интерпретатором. Так мы надеялись получить возможность реализовывать с помощью Tarantool любые сервисы и решения.
Для задач масштабирования Tarantool изначально поддерживал репликации типа Master-Replica. Причем количество реплик могло быть любым.
Со временем у нас был реализован мультиплексированный журнал (WAL, Write-Ahead-Log), который позволял хранить записи сразу с нескольких узлов. Так мы получили поддержку Master-Master-репликаций. Вместе с преимуществами такая реализация принесла и ряд трудностей: если на двух узлах одновременно производятся две записи по одному ключу, неизбежно происходит конфликт на уровне репликации, в результате которого оба мастера могут выйти из строя. Исключить такие проблемы можно с помощью разных техник. Но в нашем случае поиск таких решений был неоправданным: с помощью Master-Master-репликаций мы надеялись получить горизонтальное масштабирование записи, но на практике это невозможно. Причина в том, что взаимная запись мастеров «друг в друга» создает значительную дополнительную нагрузку по записи.
В результате мы решили отказаться от Master-Master-репликаций и для обеспечения горизонтального масштабирования написали отдельный модуль шардирования базы VShard. Он разбивает базу за предопределенное количество бакетов, а сами бакеты раскладывает на репликасеты (наборы по три реплики с одним выбранным мастером). Такая реализация гарантирует отказоустойчивость системы и доступность данных даже в случае сбоев в одном из репликасетов.
В итоге, проделав значительный путь улучшений и доработок, мы надеялись, что:
- с помощью нашей реализации можно будет решать любые задачи бизнеса;
- на базе платформы можно будет легко развивать экосистему компонентов, которые в последующем помогут строить новые решения;
- Open Source увеличит аудиторию и рынок.
Вместе с тем после анализа реального положения дел мы пришли к пониманию, что:
- из-за схожести запросов все разрабатываемые решения были во многом похожи, но кастомизировались под каждого клиента — это приводило к появлению «зоопарка решений»;
- кастомизированные решения плохо взаимодействовали между собой;
- для работы с платформой нужен был штат инженеров с навыками программирования;
- внешний вклад в развитие Open-Source-версии Tarantool был близок к нулю.
В результате мы пришли к идее создания готового решения, которое будет предлагать нужные возможности, но не будет требовать разработку с нуля — перед использованием достаточно простой настройки. Так появился Tarantool Data Grid.
Tarantool Data Grid
Tarantool Data Grid — универсальное решение для использования многих источников данных: ETL, MDM, CDC. Он умеет агрегировать данные из разрозненных систем, выполнять их преобразование и отдавать данные напрямую в приложения.
В Tarantool Data Grid мы сумели реализовать много технологий и решений, в том числе:
- модель данных;
- специальный язык запросов GraphQL;
- соответствующие API;
- роли и пользователи дополнительного уровня;
- планировщик задач и не только.
Такая реализация фактически сделала Tarantool Data Grid «швейцарским ножом» среди инструментов, с помощью которого можно решать много задач в разных сценариях.
Вместе с тем со значительным расширением функциональности продукта мы существенно усложнили его поддержку и мониторинг: в большом конгломерате технологий очень просто было упустить из вида ошибки, баги, сбои на уровне настроек и другие нюансы. Это осложняло и поддержку постоянного уровня производительности. Более того, мы видели, что практически не было клиентов, которые использовали бы всю функциональность Tarantool Data Grid: зачастую из большого стека возможностей пользователи задействовали лишь небольшую часть, а выбор в пользу Tarantool Data Grid делали из-за возможности получить все нужные функции «из одной коробки».
Улучшение UX Tarantool
Одновременно с разработкой Tarantool Data Grid мы пришли к пониманию необходимости разработки GUI (Graphical User Interface, графический пользовательский интерфейс). Мы назвали его Cartridge.
Также мы разработали методику под названием Role для написания распределенных программ, возникающих в кластере. Каждая роль отвечает за решение конкретных задач: каждый экземпляр приложения может реализовывать роли одного или нескольких типов. Причем в кластере может быть несколько одинаковых по типу ролей.
Алгоритм работы с ролями прост:
- описывается небольшой фрагмент Lua-кода;
- указывается, к какому узлу или набору узлов применима роль;
- настройки распространяются по всему кластеру;
- роли запускаются только на тех узлах, где применяются через настройки.
Но в Tarantool по-прежнему оставались некоторые подводные камни. Проблема заключалась в том, что UI, роли и другие реализованные решения запускались на тех же узлах, которые занимались исполнением кода и хранением информации (фактически на кластере, занятом клиентской работой). Это приводило к «штормам» — ситуациям, при которых на фоне недостаточной связности шарды внутри кластера начинали условно бесконечную реконфигурацию с постоянными попытками переключить мастеров. В итоге шарды не видели друг друга и не отвечали координаторам или соседям: кластер был занят исключительно реконфигурацией, и остановить этот процесс можно было только выключением кластера. Это было большой проблемой еще и потому, что от таких штормов страдали кластеры, обслуживающие пользовательские нагрузки.
В итоге мы решили заменить Cartridge с его проблемами новым Cluster Manager — централизованным решением для управления большими кластерами с GUI. Его мы сделали Stand-Alone-аппликацией — он занимается исключительно тем, что мониторит кластер, реагирует на его изменения, но сам кластер при этом не затрагивает.
Кроме того, мы обеспечили поддержку декларативного определения конфига кластера — весь кластер описывается с перечислением, где и какие узлы стоят. При этом подход с использованием ролей для описания аппликаций остался без изменений.
Одно из главных преимуществ Cluster Manager — централизованное хранилище конфигураций. Благодаря такому варианту хранения все изменения хранятся на отдельном кластере из нескольких нод, а остальные ноды подписываются на изменения и получают их «адресно». Это исключает необходимость парсить весь конфиг, снимая значительную долю проблем и лишних нагрузок.
Дальнейшее развитие платформы
В рамках развития платформы Tarantool мы не ограничивались созданием новых продуктов или интерфейсов. Мы также планомерно вносили существенные доработки на уровне технологий, которые потенциально расширяли пул задач, посильных платформе. Одним из нововведений была синхронная репликация.
Так, основным недостатком асинхронной репликации является то, что клиент может получить ответ раньше, чем запись попадает на реплику (после записи на мастера). Это чревато рисками:
- нет гарантий, что данные попадают на реплику;
- в случае сбоя на мастере часть данных потенциально может потеряться (если они не успевают попасть на реплику);
- даже в случае активного мастера при чтении с реплики можно «попасть» на неактуальные данные (если записи еще не успели попасть на реплику).
Синхронная репликация исключает подобные риски: мастер сначала получает подтверждение, что данные успешно попали на реплику, и только потом отвечает клиенту. Таким образом, даже при чтении с реплики клиент может быть уверен, что получает актуальные, консистентные данные. Это повышает гарантии.
Поверх синхронной репликации мы реализовали алгоритм консенсуса Raft для распределенных систем. Он нужен, чтобы участники могли совместно решать, произошло ли изменение состояния базы (удачна запись или нет). Чтобы обеспечить консенсус, в Raft сначала определяется лидер, который:
- управляет распределенным логом;
- принимает запросы от клиентов;
- реплицирует запросы на остальные серверы в кластере.
В случае выхода лидера из строя в кластере выбирается новый лидер.
Благодаря такому алгоритму Raft дает строгие гарантии консистентности. При этом остается возможность читать «мимо мастера» — например, мастер можно задействовать только под запись, а чтение организовать с реплик. Для обеспечения консистентности мы также реализовали линеаризуемые чтения.
Tarantool Clusters Federation
Одной из фундаментальных задач развития платформы и ее возможностей было и остается обеспечение отказоустойчивости и катастрофоустойчивости решений.
Синхронная репликация требует, чтобы в каждом репликасете было минимум три ноды: это нужно, чтобы в случае отключения одной из нод две другие могли выбрать лидера и продолжить стабильно работать.
При этом большинство наших клиентов используют два центра обработки данных, что отчасти затрудняет выполнение этих требований:
- Разделить три ноды на два ЦОДа — задача «со звездочкой».
- В случае падения ЦОДа с двумя нодами система получает ощутимый ущерб и не может выбрать лидера.
Чтобы гарантировать устойчивость в такой ситуации, мы разработали Tarantool Clusters Federation — инструмент, который позволяет повысить катастрофоустойчивость инфраструктуры за счет переключения независимых кластеров Tarantool в существующей архитектуре без даунтайма.
Одним из ключевых элементов Tarantool Clusters Federation является координатор, который непрерывно отслеживает состояние двух кластеров (один в режиме Active, другой в режиме Passive) с настроенной между ними асинхронной репликацией и в случае аварии в активном дата-центре автоматически переключает систему на резервный кластер.
Примечательно, что Tarantool Clusters Federation уже прошел боевое крещение в реальных условиях и сработал успешно.
Подобный алгоритм работы Tarantool Clusters Federation с его координатором можно задействовать и в других сценариях. Например, можно, временно отключив репликацию, произвести тестирование новой версии бэкенда и аппликации на пассивном кластере. В таком случае активный кластер не будет затрагиваться, что исключает риск влияния на нагрузку в проде. При этом появляется возможность безопасно и без простоев накатывать и проверять обновления.
От платформы к коробке
Прокачав платформу Tarantool до высокого уровня зрелости, мы решили, не теряя фокус с платформы, сосредоточиться на развитии отдельных коробочных продуктов, которые смогли бы решать конкретные задачи пользователей.
Так в портфеле Tarantool появился целый пул новых инструментов.
Tarantool DB
Tarantool DB — решение для простого создания и работы с хранилищем данных с поддержкой интерфейса доступа по протоколам Redis и IPROTO.
Одно из ключевых достоинств Tarantool DB — повышенные гарантии надежности. Так, в решении реализована синхронная репликация на уровне кластеров, поддержка Tarantool Clusters Federation, WAL и другие возможности.
Более того, в Tarantool DB мы реализовали возможности и функции, которые позволяют рассматривать его в качестве альтернативы Redis (в поставке продукта есть механизм Drop‑in‑замены с Redis на Tarantool).
Примечательно, что Tarantool DB — классическое коробочное решение, которое можно купить, развернуть и сразу начать использовать без манипуляций на уровне кода.
Tarantool CDC (Change Data Capture)
Tarantool Change Data Capture — репликатор, который забирает данные из основной СУБД, не нагружая ее.
С Tarantool CDC отпадает необходимость в лицензиях на дополнительные продукты. При этом можно сократить расходы на обслуживание, собирая и обрабатывая в онлайне данные из большинства популярных реляционных СУБД.
За счет нашего репликатора можно организовать обработку данных с помощью брокеров сообщений, построить кэш или витрину данных.
Tarantool CDC обеспечивает высокую производительность и перенос данных, обновляемых в реальном времени, без необходимости остановки БД.
Причем Tarantool CDC подходит для систем обработки данных свыше 100 тысяч TPS.
Tarantool Graph DB
Tarantool Graph DB — графово-векторная база данных, которую можно использовать для моделирования сложных структур данных.
Так, Graph DB можно использовать в сценариях, где требуется:
- анализ связей между данными в режиме реального времени;
- снижение рисков мошенничества с финансовыми операциями и налоговыми транзакциями;
- анализ поведения и предпочтений клиентов;
- анализ цепочек поставок для оптимизации маршрутов и не только.
У Graph DB довольно широкий пул возможностей в части операций с графовыми данными, эксплуатации и обеспечения безопасности, обработки векторов данных вершин графа и не только.
Tarantool Queue Enterprise
Tarantool Queue Enterprise — распределенная In‑memory-система очередей сообщений, которая позволяет создавать очереди с разной архитектурой под разные сценарии использования в зависимости от задач бизнеса.
Tarantool Queue Enterprise поддерживает два варианта очередей:
- SQ — шардированная очередь с возможностью отправки отложенных сообщений и настройкой приоритетов. Подходит для обработки заказов, маршрутизации и балансировки нагрузки, управления контентом и задачами, других сценариев.
- MQ — брокер со строгим порядком обработки сообщений. Подходит для использования в системах, связанных с высокими нагрузками: обработкой Big Data, потоковой обработкой, работой в режиме реального времени.
Выводы и планы на будущее
Наш опыт показывает, что развитие большой платформы — это всегда длинный и сложный путь, на котором бывают не только верные решения, но и ошибки. При этом успех развития такого продукта всегда зависит от способности быстро адаптироваться к потребностям бизнеса, возникающим вызовам, принимать смелые решения.
Одновременно с этим не обязательно фокусировать ресурсы всей команды только на одном проекте: зачастую это ограничивает, мешает получать новые импульсы для развития.
Понимая это, наряду с продолжением поддержки и развития платформы Tarantool мы начали разработку коробочных продуктов. С переходом к такой концепции мы смогли сгладить кривую входа в Tarantool, сделав работу с инструментами интуитивнее и прозрачнее для пользователя без ущерба возможностям предлагаемых продуктов.