Зачем вообще нужны витрины и тем более Система для их построения?
Если коротко, то витрины (витрина от англ. data mart) – это набор структурированных данных. Обычно это данные по определенной теме или задаче в компании. Например, витрина с данными о заказчиках для отдела маркетинга может содержать подробные данные по договорам, истории заказов и поставок, оплатах, звонках и адресах доставки. Ничего лишнего, только нужные и актуальные очищенные данные, полученные из других ИС предприятия. Таких витрин даже на одном предприятии может быть множество.
Чаще всего с помощью витрин анализируют данные и строят ML-модели. Также витрины могут использоваться на предприятиях в качестве мастер-данных, например как справочники. Помимо этого, витрина может выступать периферическим узлом в сетях обмена данными между различными участниками. Примером концепции построения таких сетей для обмена данными является Data mesh (вот тут есть хороший перевод статьи по теме Хабр).
Типовой проект внедрения витрин состоит из технологической и прикладной частей. Если для решения технологических задач брать готовый инструмент, а не писать систему с нуля, то можно заложить больше ресурсов на прикладные задачи, которым зачастую уделяют незаслуженно мало внимания. Для B2B и других проектов, предполагающих внедрение множества витрин у различных заказчиков, готовый инструмент позволит существенно снизить технические риски, уменьшить затраты и сократить сроки внедрения.
Что требуется от витрины?
Сразу хотелось бы ответить на вопрос: а почему нельзя просто взять любую из существующих СУБД и сразу закрыть технологические задачи?
![](https://habrastorage.org/getpro/habr/upload_files/292/3f4/018/2923f4018cb743c2dcb1516036cc09a4.png)
На самом деле, можно, но, как обычно, всё дело в деталях, а точнее в требованиях к витринам, которые нередко упускаются из вида и могут болезненно проявиться уже на поздних этапах, например при ОПЭ:
Изоляция данных. Обновление данных, например загрузка справочника, может быть растянуто во времени, при этом до окончания загрузки текущая версия справочника должна быть полностью доступна с исключением «грязного чтения» загружаемой версии.
Гарантии атомарности операций при обновлении данных. В случае сбоев и ошибок загрузки данных витрина остаётся в состоянии, которое предшествовало сбойному процессу. Другими словами, или данные обновляются полностью, или не обновляются вовсе, не оставляя следов сбойных операций.
Устойчивость к дубликатам изменений. Весьма сложно и дорого реализовывать во всех ИС-источниках данных выгрузку по принципу exactly-once. Наличие дублей одинаковых изменений объектов не должно приводить к нарушению логической целостности состояния витрин.
Системная темпоральность. Мало какая реляционная СУБД имеет функцию системной темпоральности «из коробки». Ведение системного времени и версионирование записей по системному времени позволяет сравнивать состояние данных витрины между двумя разными моментами времени или проводить «расследование», основываясь на данных, которые были в витрине в определенный момент в прошлом. Одним из вариантов обеспечения темпоральности является реализация SCD2 с ведением диапазонов сроков действия для версий записи.
Эффективное выполнение различных видов запросов: сравнительно редких и тяжелых аналитических запросов, затрагивающих большой объем данных (OLAP-нагрузка), и множества одновременных простых запросов (OLTP-нагрузка). Как правило, СУБД заточены на какой-то один вариант нагрузки: OLAP или OLTP.
Концепция
С середины 2020 года наша команда разрабатывает Систему, предназначенную для построения витрин данных. Начав с разработки прототипа, мы продолжили развивать функционал в рамках той же архитектуры. Сейчас это открытое программное обеспечение, которое мы используем при внедрениях витрин данных.
У нас в тех. проекте записано: «Простор – интеграционная система, обеспечивающая унифицированный интерфейс темпоральной реляционной СУБД к гетерогенному хранилищу данных». Гетерогенное хранилище позволяет использовать сильные стороны каждой из СУБД, входящих в состав хранилища, и не быть заложником недостатков одной из них.
В Просторе гетерогенное хранилище представлено такими СУБД:
Greenplum – аналитическая СУБД, предназначенная для OLAP-нагрузки. Хорошо горизонтально масштабируется, имеет высокий уровень поддержки стандарта SQL.
Clickhouse – аналитическая СУБД. Демонстрирует одни из лучших в классе показатели выполнения агрегационных запросов. Не полностью поддерживает SQL и имеет ряд иных ограничений при эксплуатации, например при изменении или удалении записей.
Tarantool – In-memory СУБД с персистентным хранением данных. Отличные показатели при OLTP-нагрузке (чтение отдельных записей). В кластерном режиме имеет ограничения по исполнению SQL-запросов.
PostgreSQL – всеми любимая реляционная СУБД. Хорошо держит OLTP-нагрузку, но горизонтально не масштабируется и, соответственно, не подходит для аналитических запросов с действительно большим объемом данных.
Состав СУБД хранилища данных можно изменять в зависимости от характера предполагаемой нагрузки или уже в процессе эксплуатации. Для небольших витрин можно использовать одну СУБД, например PostgreSQL. Для крупных витрин, содержащих большие объемы данных и предполагающих разнородные запросы, можно использовать различные сочетания, например Greenplum + Tarantool или Greenplum + Tarantool + Clickhouse.
Ядро системы – сервис, выполняющий роль координатора и диспетчера. Обеспечивает единый интерфейс доступа, маршрутизирует запросы, управляет процессами загрузки и выгрузки данных, контролирует целостность данных. Также ядро парсит входящие SQL-запросы и обогащает их до вида, готового к исполнению в той или иной СУБД. Непосредственно выполнением запросов занимаются СУБД хранилища.
Обмен большими объемами данных между витриной и поставщиками/потребителями этих данных выполняется через Kafka. Но если речь идет о небольших объемах данных (сотни записей), то загружать или читать данные можно напрямую через Ядро.
Ядро управляет специальными компонентами – коннекторами, предназначенными для массивно-параллельной загрузки данных из Kafka в СУБД хранилища и массивно-параллельной выгрузки данных в Kafka из СУБД хранилища.
С точки зрения пользователя
Если пользователем называть поставщика или потребителя данных, то с точки зрения такого «пользователя» Простор выглядит так:
Единый интерфейс доступа – JDBC 4.2. Подключиться к Простору можно как к обычной реляционной СУБД, например, используя SQL-клиент, в котором доступны все элементы логической модели и запросы к ним.
Единая логическая реляционная модель данных, скрывающая «под капотом» реальные физические модели данных СУБД хранилища.
При изменении логической модели данных автоматически изменяются и соответствующие физические модели в СУБД хранилища. Логическая модель – внешнее пользовательское представление модели данных витрины. Включает следующие логические сущности:
a. Логическая таблица (table) – для «пользователя» это обычная таблица, но с возможностью указать момент времени в прошлом, относительно которого требуется «наблюдать» данные таблицы.
SELECT * FROM customers FOR SYSTEM_TIME AS OF '2021-12-01 15:00:00'
Также для логической таблицы можно ограничить СУБД хранилища, в которых она будет физически расположена.
b. Логическое представление (view) – сохраненный именованный SQL-запрос, к которому можно выполнять запросы, также с возможностью указания момента времени «наблюдения» данных.
c. Логическое материализованное представление (materialized view) – необычная логическая таблица, новые или измененные данные в которую попадают автоматически на основании сохраненного запроса к другим логическим таблицам, расположенным в других СУБД хранилища. Особой возможностью запросов к логическим материализованным представлениям является автоматическое перенаправление такого запроса к исходным логическим таблицам, если отставание данных материализованного представления больше заданного предела. Материализованные представления позволяют реализовать более интересные варианты топологии витрины, в которых одна из СУБД исполняет роль отказоустойчивого мастера, а другая — содержит материализованные read-only-представления.
d. Логическая внешняя таблица – виртуальная таблица, по сути являющаяся указателем на источник или приёмник данных. Записывая или считывая данные из этой таблицы, можно управлять загрузкой и выгрузкой данных.
Язык запросов – подмножество стандарта SQL с дополнительными функциями и командами. Позволяет управлять состоянием, моделью данных и самими данными витрины. Запросы на выборку данных автоматически маршрутизируются в наиболее эффективную для их исполнения СУБД хранилища из доступных.
Отдельно стоит упомянуть механизм дельт, позволяющий «пользователю» указывать начало и конец логически целостной пачки изменений. Внешне этот механизм несколько напоминает ACID-транзакции, позволяя обрамить набор операций по изменению данных витрины командами начала дельты и ее окончания (комита).
-- открыть новую дельту BEGIN DELTA; -- загрузка данных в логическую таблицу customers из Kafka INSERT INTO customers SELECT * FROM customers_kafka_ext; -- загрузка данных в логическую таблицу calls из Kafka INSERT INTO calls SELECT * FROM calls_kafka_ext; -- загрузка данных в логическую таблицу balance из Kafka INSERT INTO balance SELECT * FROM balance_kafka_ext; -- закрыть дельту COMMIT DELTA;
Все изменения, выполненные в одной дельте, помечаются единой меткой времени комита дельты. Изменения данных, производимые в рамках открытой дельты, изолированы от пользовательских запросов с целью исключения «грязного чтения». Можно утверждать, что изменения в рамках дельты доступны для пользователя целиком и одномоментно или не доступны вовсе. Если необходимо, то открытую дельту можно откатить.
Неотъемлемой частью Простора как продукта является подробная открытая документация, обновляемая одновременно с выпуском каждого релиза. С перечнем базовых функций и примерами их использования можно ознакомиться по ссылке.
Заключение
Простор – система для построения витрин данных, доступная под лицензией Apache 2.0. Для тестирования и ознакомления с возможностями системы можно развернуть минимальную конфигурацию, где Простор использует в качестве хранилища только PostgreSQL. Инструкция по развертыванию доступна тут. Если объем данных для витрины не очень большой, то такая конфигурация может использоваться и для PROD.
Шамота Михаил