Большинство популярных сегодня СУБД создавались для решения конкретных задач, например PostgreSQL для поддержки транзакционной рабочей нагрузки, а ClickHouse — аналитической. Поэтому для эффективного использования всех разнообразных данных компании требуется комплекс взаимосвязанных решений, например интеграция хранилищ на базе Greenplum, Hadoop, S3, ClickHouse и т. п. Однако сложно обеспечить согласованность данных в таких конфигурациях, поэтому стали развиваться решения, объединяющие под одним «зонтиком» разнородные системы хранения и обработки данных для решения, например, и транзакционных, и аналитических задач. Яркий пример — Apache Trino как единая точка входа для запросов аналитики больших данных. Но для использования таких продуктов при создании облачных платформ необходимо, чтобы они отвечали ряду дополнительных требований, в частности, мультиарендности. А вот тут все не так просто — на рынке нет готовых продуктов с открытым исходным кодом, обеспечивающих в одном архитектурном решении объединение возможностей реляционных СУБД и систем реального времени, не говоря уже о поддержке мультиарендности на уровне схем баз, а также поддержки межкластерной репликации с различными уровнями согласованности.
Для предоставления пользователям возможности одновременной работы и с транзакционными, и с аналитическими нагрузками при работе с одними и теми же данными в компании Cloud X (входит в En+ Group) была создана СУБД Cloud X Stratus DB, реализующая связку аналитической СУБД и СУБД реального времени. В системе изначально предусмотрен облачный вариант развертывания на распределенной инфраструктуре, состоящей из ЦОДов, находящихся на значительном удалении друг от друга.
Принцип PACELC и современные СУБД
У теоремы CAP есть расширение — принцип проектирования PACELC [1], согласно которому в случае сетевого разделения (P — network partitioning) в распределенной системе необходимо выбирать между доступностью (A — availability) и согласованностью (С — consistency), иначе (E — else), даже если система функционирует при отсутствии разделения, придется выбирать между задержками (L — latency) и потерей согласованности (С — consistency). Принцип PACELC идет дальше теоремы CAP и исследует репликацию данных. Например, в системе из географически удаленных узлов с разделенными данными задержки не позволяют мгновенно поддерживать согласованность, в этом случае необходимо принять решение между доступностью и согласованностью.
PACELC предлагает четыре варианта:
- PA/EL — приоритет доступности и задержки над согласованностью;
- PA/EC — если есть разделение, то выбираем доступность, в противном — согласованность;
- PC/EL — если есть разделение, выбираем согласованность, в противном — задержку;
- PC/EC — всегда выбираем согласованность.
Такие СУБД, как Dynamo, Cassandra, Riak и Cosmos DB (таблица 1), относятся к системам PA/EL — при разделении сети они делают выбор в пользу доступности, отказываясь от согласованности. При нормальной работе также отказываются от согласованности в пользу более низкой задержки. Однако, например, Cosmos DB имеет несколько уровней согласованности, которые позволяют выбирать между C/A во время разделения сети и L/C в случае нормальной работы.
СУБД MongoDB относится к PA/EC, гарантируя согласованное чтение и запись.
СУБД StratusDB поддерживает два уровня согласованности, позволяя выбирать между C/A во время разделения сети и L/C в случае нормальной работы. Настроенный уровень согласованности не нарушается, поэтому формально — это CP.
Распределенные базы данных, которые полагаются на репликацию, должны найти фундаментальный компромисс между согласованностью чтения, доступностью, задержкой и пропускной способностью, как определено расширением PACELC.
В Azure Cosmos DB [2] приведены детальные характеристики пяти уровней согласованности: Strong — сильная; Bounded staleness — ограниченное устаревание; Session — сеансовая; Consistent prefix — последовательный префикс; Eventual — окончательная согласованность.
«Золотой» стандарт организации данных — модель строгой согласованности, однако строгая согласованность добавляет высокую цену из-за больших задержек записи (данные должны реплицироваться и фиксироваться на больших расстояниях). Сильная согласованность также может страдать от снижения доступности (во время сбоев), поскольку данные не могут реплицироваться и фиксироваться в каждом регионе. Окончательная согласованность обеспечивает более высокую доступность и лучшую производительность, но разрабатывать приложения сложнее, поскольку данные могут быть несогласованными во всех регионах.
Каждый уровень обеспечивает компромиссы доступности и производительности. StratusDB обеспечивает сильную и окончательную согласованность, в перспективе в системе будет реализована и сеансовая согласованность.
При сильной согласованности пользователи всегда гарантированно читают последнюю зафиксированную запись. При обычных обстоятельствах для сильной согласованности запись считается выполненной, когда все регионы подтверждают, что запись была в нее реплицирована. Однако если регионов больше трех, то StratusDB «понижает» кворум регионов до глобального большинства в случаях, когда некоторые регионы либо не отвечают, либо отвечают медленно.
При использовании согласованности с ограниченным устареванием операции чтения, выполненные в отношении зависимого региона, не обязательно возвращают самую последнюю версию данных в глобальном масштабе, но гарантированно возвращают самую последнюю версию данных в этом регионе, которая будет находиться в пределах максимальной границы устаревания в глобальном масштабе.
В сеансовой согласованности клиентам, с помощью идентификатора сеанса (токена), гарантируется, что данные, соответствующие более старому сеансу, никогда не будут прочитаны. Однако если клиент использует более старый токен и в базу данных были внесены свежие обновления, то будет возвращена новая версия данных, несмотря на использование более старого токена сеанса. Токен используется как барьер версии, но не как конкретная (возможно, историческая) версия данных, которые должны быть извлечены из базы данных.
Сеансовая согласованность широко используется для приложений с одним и более регионами, обеспечивая задержки записи, доступность и пропускную способность чтения, сопоставимые с окончательной согласованностью. Согласованность сеанса также обеспечивает гарантии согласованности, которые соответствуют потребностям приложений, написанных для работы в контексте пользователя.
В последовательном префиксе обновления, выполненные как запись одного документа, видят окончательную согласованность.
Обновления, выполненные как пакет в рамках транзакции, возвращаются в соответствии с транзакцией, в которой они были зафиксированы. Операции записи в рамках транзакции нескольких документов всегда видны вместе.
В конечной согласованности клиент отправляет запросы на чтение любой из региональных реплик. Эта реплика может быть отстающей и может возвращать устаревшие данные или не возвращать их вообще.
Окончательная согласованность — самая слабая форма согласованности, поскольку клиент может читать значения, которые старше тех, которые он читал в прошлом. Окончательная согласованность идеальна, когда приложение не требует гарантий упорядочивания, например количество ретвитов, лайков или не связанных комментариев.
Насколько конечна окончательная согласованность? Для ответа необходимо предсказать ожидаемую согласованность хранилища данных в конечном итоге, используя модели, называемые вероятностно ограниченной устареваемостью (Probabilistically Bounded Staleness, PBS) [3]. Оказывается, что на практике при использовании окончательной согласованности в конечном итоге хранилища данных часто предоставляют согласованные данные. Используя прогнозы PBS, можно оптимизировать компромисс между задержкой и согласованностью и лучше понять, почему на практике множество пользователей хранилищ данных выбирают именно окончательную согласованность.
В таблице 2 приведено соответствие уровней согласованности и пропускной способности.
.jpg)
Основы StratusDB
В основу создания СУБД, объединяющей свойства транзакционных и аналитических решений, должны быть положены современные, активно развивающиеся продукты, имеющие поддержку многочисленных сообществ. Однозначные кандидаты — PostgreSQL и ClickHouse.
Сегодня СУБД Postgres все чаще используется совместно с другими СУБД с целью закрыть все потребности клиентов как в части транзакционной модели, так и возможности пользоваться преимуществами аналитических колоночных баз данных.
Компания ClickHouse — лидер в области аналитических баз данных в реальном времени — сделала значительный шаг, приобретя в 2024 году PeerDB [4], ведущего поставщика решений для захвата изменений данных (Change Data Capture, CDC) для баз данных PostgreSQL. Это приобретение не только подчеркнуло приверженность ClickHouse аналитике в реальном времени, но и акцентирует внимание на бесшовной интеграции разнородных данных: PostgreSQL обеспечивает транзакционные рабочие нагрузки, ClickHouse — аналитику. Подход CDC позволяет непрерывно отслеживать вставки, обновления и удаления в базе PostgreSQL и реплицирует их в ClickHouse, обеспечивая аналитику в реальном времени.
Набирает зрелость продукт с открытым исходным кодом Citus, основанный на СУБД PostgreSQL, но развивающийся в рамках парадигмы распределенных реляционных СУБД. В 2019 году компания Microsoft приобрела компанию Citus Data, занимающуюся развитием СУБД CitusDB, обеспечивающей горизонтальное масштабирование PostgreSQL в кластерной конфигурации с разбиением пространства хранения на логические разделы (partitioning) с возможностью репликации. После завершения сделки продукт CitusDB сохранил статус Open Source.
После того как лицензия Greenplum подверглась существенной модификации, будущее этой аналитической СУБД с открытым кодом стало туманным — компании, которые ее использовали, вынуждены продолжить развитие дистрибутива своими силами, сохраняя при этом открытые лицензии. Например, компания Arenadata, предлагающая продукт на базе Greenplum, выпустила Greengage [5].
Citus
Citus позволяет создавать распределенные масштабируемые кластеры баз данных, что наделяет СУБД PostgreSQLs новыми функциями через использование расширений к ее свежим релизам, в то время как в Greenplum использовалась старая версия PostgreSQL, а переход на новую версию требовал существенных затрат.
Citus добавляет к СУБД PostgreSQL шардинг, распределенные таблицы, справочные таблицы, распределенный механизм запросов, хранилище по колонкам и возможность обращения из любого узла. Мастер-узел в Greenplum может стать узким местом.
Сочетание параллелизма Citus, хранения большего количества данных в памяти и высокой пропускной способности ввода-вывода может означать значительное повышение производительности для многопользовательских приложений SaaS, клиентских аналитических панелей реального времени и рабочих нагрузок временных рядов.
Одно из требований к облачной платформе данных — мультиарендность. Citus поддерживает изоляцию арендаторов для предоставления гарантий их производительности и следует концепции справочных таблиц для уменьшения дублирования данных между арендаторами. Эти возможности позволяют масштабировать данные арендаторов на многих машинах и, в зависимости от потребностей, осуществлять настройку вычислительных ресурсов и памяти. Кроме того, совместное использование несколькими арендаторами одной и той же схемы базы данных позволяет эффективно использовать аппаратные ресурсы и упрощает управление базой данных.
Citus позволяет применять логику шардинга в базе данных, а не в приложении; получить новый продукт без отказа от мощи SQL PostgreSQL; изолировать ресурсы крупных и мелких пользователей.
ClickHouse
Сегодня СУБД ClickHouse — это фактически промышленный стандарт аналитических баз данных реального времени. Формат хранения данных в виде столбцов предполагает, что каждый столбец данных хранится независимо от других, что позволяет системе выполнять сложные запросы за секунды, запрашивая только несколько колонок. Система может обращаться только к тем столбцам, которые фактически требуются для выполнения запроса, а не обрабатывать данные в колонках, которые не участвуют в запросе. Кроме того, такой формат позволяет эффективно сжимать данные по столбцам для экономии места в хранилище. Иначе говоря, для числовых столбцов можно использовать сжатие, наилучшим образом подходящее для числовых данных, а для текстовых — сжатие, оптимизированное именно для текстов.
Высокая производительность ClickHouse в значительной степени обусловлена еще и асинхронной мультимастер-репликацией и распределенной обработкой запросов. Эти особенности позволяют обрабатывать большие объемы данных и выполнять несколько запросов одновременно, не снижая производительность.
Асинхронная мультимастер-репликация позволяет создавать резервные копии данных и обеспечивать отказоустойчивость системы — такой метод репликации данных в базе позволяет копировать данные между несколькими узлами (мастер-узлами) в распределенной системе базы данных, при этом узлы могут одновременно выполнять как операции чтения, так и записи.
ClickHouse использует SQL для загрузки и модификации данных в различные формы. Это крайне важная опция, поскольку подавляющее большинство разработчиков уже хорошо освоили этот язык, а поддержка расширенного SQL способствует легкому освоению новыми пользователями.
Способность ClickHouse обрабатывать данные в реальном времени обусловлена также возможностью генерации мгновенных результатов даже при наличии миллиардов строк во введенных данных. СУБД может использовать всю оперативную память и все ядра процессора в серверах кластеров. Благодаря этому ClickHouse функционирует в низколатентной среде, что важно для аналитики реального времени при создании информационных панелей (дашбордов).
Параллельная обработка — важная часть механизма обработки данных ClickHouse. Она повышает эффективность выполнения запросов за счет разделения задач между несколькими рабочими узлами (воркерами). Параллельная обработка особенно важна при выполнении операций вставки, обработки данных и запросов к записям.
Репликация данных из PostgreSQL
Центральная проблема при создании географически распределенных платформ данных — обеспечение быстрого и надежного способа репликации данных, находящихся как внутри инстанса базы (из PostgreSQL в ClickHouse), так и надежного механизма межрегиональной репликации. Одним из вдохновителей в реализации репликации стал продукт PeerDB. СУБД StrаtusDB также использует логические слоты репликации Postgres для реализации захвата измененных данных (CDC). Логические слоты репликации обеспечивают поток операций INSERT, UPDATE и DELETE в базе данных PostgreSQL.
Одна из проблем использования логических слотов репликации связана с возможностью разрастания журнала опережающей записи WAL (Write-Ahead Logging), создающего риск сбоя базы данных PostgreSQL. В PeerDB для журнала используется промежуточное хранилище S3, а StratusDB решает эту проблему, используя быстрое хранение в памяти. Однако команда PeerDB утверждает, что поддерживает различные режимы потоковой передачи не только на основе журнала (CDC), но и на основе временной метки, а также на основе хmin — идентификатора вставочной транзакции, системного столбца таблицы Postgres. Stratus DB использует временные метки для разрешения конфликтов при межрегиональной репликации.
Другая проблема заключается в необходимости распараллеливания чтения данных из PostgreSQL. Согласно идеям поддержки автоматического внутризапросного параллелизма, реализованными в DuckDB, в СУБД Stratus DB также имеется распараллеливание сканирования таблиц PostgreSQL. При открытии нескольких подключений к Postgres одновременно считываются разные части таблицы. Чтобы эффективно разделить чтение таблицы, используется оператор Postgres TID Scan (Tuple ID), который позволяет запросу считывать указанный диапазон идентификаторов кортежей из таблицы. Идентификаторы кортежей имеют вид (page, tuple). Распараллеливание сканирования таблицы PostgreSQL происходит на основе диапазонов страниц базы данных, выраженных в TID. Предполагается, что каждая задача сканирования считывает 1000 страниц. Например, чтобы прочитать таблицу, состоящую из 2500 страниц, запускается три задачи сканирования с необходимыми диапазонами TID. Наличие открытой границы для последнего диапазона важно, поскольку количество страниц является всего лишь оценкой. Таким образом, можно эффективно сканировать таблицу параллельно, не полагаясь на схему. Поскольку размер страницы в PostgreSQL фиксирован, это также имеет дополнительный бонус в виде выравнивания усилий по чтению подмножества страницы независимо от количества столбцов в каждой строке. Однако в этом решении есть свои подводные камни, так как, согласно документации, идентификатор кортежа может быть изменен такими операциями, как VACUUM ALL. Но решение имеется — транзакционная синхронизация.
СУБД PostgreSQL — транзакционная база данных, поэтому нужно обрабатывать параллельные изменения в таблице, которая сканируется параллельно. Эта проблема решается путем создания новой транзакции только для чтения во время планирования запросов. Эта транзакция остается запущенной до тех пор, пока полностью не завершится чтение таблицы. Для этих целей необходимо использовать еще одну функцию Postgres, pg_export_snapshot (), которая позволяет получать текущий контекст транзакции в одном соединении, а затем импортировать его в параллельные соединения для чтения. Таким образом, все соединения, связанные с одним сканированием таблицы, будут видеть состояние таблицы точно таким же, каким оно было в самом начале сканирования на протяжении всего потенциально длительного процесса чтения.
Межрегиональная репликация данных
СУБД StratusDB изначально создавалась для использования в облачных конфигурациях, распределенных по разным географическим регионам, которые в свою очередь содержат несколько зон доступности (availability zones) по количеству ЦОД.
Репликация между центрами обработки данных (Cross Data Center Replication, XDCR) в данном случае имеет региональный контекст, так как малые сетевые задержки внутри региона позволяют строить «растянутые» кластеры СУБД в указанном регионе.
В StratusDB имеется один механизм однонаправленной репликации, что не мешает создавать двунаправленные топологии путем реализации двух однонаправленных репликаций в противоположных направлениях между кластерами.
Механизм межрегионального распространения данных основан на выделении домашнего региона и зависимых регионов.
Любые записи, поступающие в зависимые регионы, фиксируются кворумом в локальном регионе, а затем отправляются в домашний регион для разрешения конфликта, асинхронно. Как только запись попадает в домашний регион, конфликт разрешается, она становится «подтвержденной» записью. До тех пор она называется «предварительной» записью или «неподтвержденной» записью, по аналогии с Cosmos DB.
Любая запись, обслуживаемая из домашнего региона, немедленно становится подтвержденной записью.
Last Write Wins — это политика разрешения конфликтов по умолчанию, которая использует временную метку _tswrite для следующих API: SQL, MongoDB, Cassandra, Gremlin и др. Соответственно, добавляются две временные метки: _tswrite — время сервера, когда была записана сущность; _tscommit — время разрешения конфликта или подтверждения его отсутствия.
Архитектура Stratus DB
Архитектура Stratus DB состоит из нескольких компонентов (см. рисунок), отвечающих за хранение транзакционных и аналитических данных, центрального компонента Stratus DB agent и Брокера сообщений.
.jpg)
Брокер сообщений отвечает за доставку реплицируемых данных. Основными критериями при выборе Брокера были: горизонтальная масштабируемость, гарантия строгого порядка и согласованности, долговечность хранилища с низкой задержкой, мультиарендность, поддержка георепликации и т. д. Таким требованиям отвечают Apache Kafka с Mirror Maker и Apache Pulsar. После тестирования и опытной эксплуатации выбор пал на Kafka.
Stratus DB agent — горизонтально масштабируемый сервис, отвечающий за чтение журналов опережающей записи и его применения по установленному уровню согласованности.
Проект СУБД Stratus DB нацелен в первую очередь на создание облачных платформ данных, в частности, развернутых на удаленных друг от друга серверных площадках, например, расположенных в разных регионах. Вместе с тем ничто не мешает применять систему в качестве платформы данных для организаций различного масштаба. Cloud X Startus DB охватывает возможности корпоративного хранилища данных, аналитической СУБД реального времени и позволяет работать как с транзакционными, так и с аналитическими видами нагрузок.
***
Система Cloud X Stratus DB развернута сейчас в опытно-промышленной конфигурации внутренних компонентов облака, в котором смоделировано несколько регионов с несколькими зонами доступности в каждом, и содержит несколько десятков терабайт данных. Благодаря использованию Kubernetes эта СУБД может быть оперативно развернута в любом ЦОДе. Кроме того, осуществляется межрегиональная репликация данных с использованием нескольких уровней их согласованности.
В перспективе планируется реализовать несколько уровней согласованности распределенных данных, помимо сильной и окончательной.
Литература
1. Daniel J. Abadi. Consistency Tradeoffs in Modern Distributed Database System Design) // Yale University. — 2012. URL: https://www.cs.umd.edu/~abadi/papers/abadi-pacelc.pdf (дата обращения: 19.05.2025).
2. Consistency levels in Azure Cosmos DB // Microsoft Corp. — 2024. URL: https://learn.microsoft.com/en-us/azure/cosmos-db/consistency-levels (дата обращения: 26.09.2024).
3. PBS: Probabilistically Bounded Staleness// The University of California, Berkeley, 2012. URL: http://pbs.cs.berkeley.edu/ (дата обращения: 20.05.2025).
4. ClickHouse acquires PeerDB to boost real-time analytics with Postgres CDC integration // ClickHouse. — 2024. URL: https://ClickHouse.com/blog/ClickHouse-acquires-peerdb-to-boost-real-time-analytics-with-postgres-cdc-integration (дата обращения: 20.05.2025).
5. Greengage: новый open source продукт на основе Greenplum // Arenadata — 2024. URL: https://arenadata.tech/about/news/greengage-novyj-open-source-produkt-na-osnove-greenplum (дата обращения: 20.05.2025).
Владимир Пугачев (PugachevVV@cloudx.group) — главный архитектор больших данных, компания Cloud X, номинант на премию Data Award 2025 (Москва).