Как материализованные представления в потоковой базе данных с CDC-подходом и шаблоном CQRS позволяют реализовать масштабируемую и высокопроизводительную систему с микросервисной архитектурой для транзакций и аналитики данных в реальном времени. Разбираемся с паттернами проектирования микросервисов на примере интернет-магазина.
Что не так с шаблоном композиция API и другие проблемы микросервисной архитектуры в управлении данными
Микросервисная архитектура для распределенных систем позволяет обеспечить гибкость, масштабируемость и отказоустойчивость. Однако, как мы уже упоминали здесь, запрос данных из нескольких микросервисов в режиме реального времени может оказаться сложной задачей, поскольку для этого могут потребоваться сложные и трудоемкие операции извлечения данных. Материализованные представления вместе с паттерном проектирования разделения ответственности команд и запросов (CQRS, Command Query Responsibility Segregation) могут решить эту проблему, обеспечивая эффективный запрос данных микросервисов в режиме реального времени.
В качестве примера возьмем интернет-магазин с микросервисной архитектурой. Разделим большую систему по микросервисам на основании ключевых объектов управления: товары, каталоги, клиенты, запасы и заказы. Каждый микросервис отвечает за обработку определенного домена или бизнес-функции и хранение данных в своем собственном хранилище данных, реализуя шаблон Database per Service.
Без материализованных представлений запрос данных из нескольких микросервисов в режиме реального времени может быть затруднен. Например, когда клиент ищет продукт на веб-сайте, необходимо получить информацию о продукте, каталог, цены и состояние запасов из различных микросервисов. Это приводит к множеству двусторонних запросов к разным микросервисам, увеличивая время отклика и нагрузку на базы данных. Самое простое решение, чтобы агрегировать клиентские запросы к нескольким микросервисам в одном вызове API.
Это решение соответствует шаблону композиции API (API Composition). Суть этого паттерна в том, что он реализует запрос, вызывая сервисы, владеющие данными, и выполняет объединение результатов в памяти. Этот прием часто использует другой шаблон проектирования микросервисной архитектуры, шлюз API (API Gareway). Шаблон композиции API является достаточно простым в реализации. В частности, реализовать его можно с помощью технологии GraphQL, которая позволяет клиенту запрашивать только нужные данные из нескольких источников в одном запросе, выполняя федерализацию нескольких схем данных. Подробнее про GraphQL мы писали здесь.
Однако, для GraphQL характерны риски доступа клиента к непредназначенным для него данным. Кроме того, при использовании шаблона композиции API некоторые запросы могут привести к неэффективному объединению больших наборов данных в памяти. Поэтому для этого шаблона характерны проблемы с масштабируемостью и обслуживанием. Также такое архитектурное решение приводит к тесной связи между микросервисами, что считается антипаттерном. Сильная связность между микросервисами противоречит самой идее микросервисной архитектуры. В частности, при запросах к микросервисам необходимо знать структуру данных, возвращаемую запрашиваемыми микросервисами. Кроме того, усложняется реализация, поскольку требуется дополнительная логика для агрегирования и объединения данных из нескольких микросервисов. Композиция API может привести к дополнительным потерям производительности, поскольку микросервису оркестратора нужно дождаться ответов от нескольких микросервисов, прежде чем возвращать результат клиенту. При этом не получиться обеспечить обновление данных из нескольких микросервисов в режиме реального времени. Если данные в запрошенных микросервисах часто изменяются, композиция API может не отражать самые последние данные, что чревато снижением качества данных и устаревшеми сведениями в результатах запроса. Альтернативой является использование материализованных представлений и CDC-подход, что мы рассмотрим далее.
CDC, CQRS и запросы с материализованными представлениями
Изменим архитектуру проектируемой системы, используя захват измененных данных (CDC, Change Data Capture) и материализованные представления для оптимизации запросов к микросервисам в режиме реального времени и повышения производительности.
CDC-подход используется в микросервисах для отслеживания изменений в базах данных. Обычно это реализуется с помощью специализированных продуктов или самописные решения, о чем мы писали здесь. Это позволяет уведомлять несколько микросервисов о любых изменениях данных, чтобы их можно было соответствующим образом обновить. Такой механизм экономит много времени, позволяя работать только с ограниченным объемом измененных данных вместо полного сканирования базы. Чтобы использовать CDC с микросервисами, механизм захвата измененных данных должен быть интегрирован в каждый из них еще на этапе проектирования приложения. При этом необходимо решить следующие вопросы:
- Как фиксировать изменения данных – через триггеры на таблицах БД, опросы, логи или готовые решения типа Debezium. Триггеры, как частный случай хранимых процедур, могут использоваться для выполнения действия при определенных событиях. Подробнее о сходстве и различии триггеров и хранимых процедур мы писали здесь на примере Greenplum. Опрос регулярно запрашивает базу данных, чтобы узнать, были ли внесены изменения. Логи фиксируют всю активность базы данных, включая изменения, и могут использоваться для обработки в реальном времени. Каждый из подходов имеет свои достоинства и недостатки, которые следует учитывать для каждого конкретного сценария.
- Как передавать изменения данных – синхронно или асинхронно. Синхронная связь полезна для кратковременных транзакций, а асинхронная связь идеальна для длительных процессов.
- Как обеспечить согласованность данных между сервисами – через использование распределенных транзакций, что чревато проблемами с производительностью, или через согласованность в конечном счете, когда каждый сервис работает со своими собственными данными и в конечном итоге становится согласованным с другими приложениями.
В рассматриваемом примере интернет-магазина CDC-подход можно использовать для управления запасами. Например, каждый раз, когда товар добавляется, обновляется или удаляется из каталога, механизм CDC фиксирует изменение и отправляет его в микросервисы, отвечающие за управление товарами и запасами. Так CDC позволяет поддерживать актуальность наличия товаров, гарантируя клиентам постоянный доступ к нужным им продуктам.
CDC позволяет реализовать инкрементные обновления хранилища данных, фиксируя изменения, внесенные в системе-источнике, чтобы загружать только их в DWH. Это сокращает время, необходимое для полной загрузки, и обеспечивает постоянную актуальность данных в хранилище данных. Также CDC можно использовать для потоковой передачи данных из нескольких источников с целью их анализа в реальном времени. Наконец, CDC пригодится для обновления моделей AI/ML новыми данными. CDC фиксирует изменения, внесенные в исходную базу данных, и обновляет модели AI/ML новыми данными. Это помогает обновлять ML-модели с использованием самых последних данных, повышая их точность.
Впрочем, помимо CDC-подхода в рассматриваемом кейсе интернет-магазина имеет смысл использовать и другой паттерн управления данными в микросервисной архитектуре – CQRS, суть которого в отделении запросов от команд. CQRS предполагает наличие базы данных представления, которая является доступной только для чтения репликой, предназначенной для поддержки запросов. Приложение поддерживает реплику в актуальном состоянии, подписываясь на события домена, публикуемые сервисом, которому принадлежат данные. Этот шаблон поддерживает несколько денормализованных представлений, которые являются масштабируемыми и производительными. Он позволяет упростить модели команд и запросов, что полезно в EDA-архитектуре, управляемой событиями в реальном времени.
Однако, CQRS как шаблон проектирования, имеет следующие недостатки: повышенная сложность, возможное дублирование кода, задержка репликации и представления, согласованные в конечном счете.
Тем не менее, CQRS позиционируется как альтернатива шаблону композиция API без проблем с масштабируемостью и производительностью. Для реализации CQRS следует определить команды, которые будут изменять данные, и запросы, которые будут считывать данные. Такое разделение позволяет оптимизировать каждую операцию независимо. Например, товары могут храниться и обновляться в классической базе данных, а списки товаров, результаты поиска, история заказов или рекомендации пользователей могут быть материализованными представлениями в потоковой база данных, которые обновляются в режиме реального времени на основе входящих событий.
Материализованные представления — это предварительно вычисленные представления данных, которые хранятся и обновляются независимо от основной транзакционной базы данных. Их можно использовать для оптимизации операций чтения за счет уменьшения сложности и задержки, связанных с запросами к основной базе данных.
Сперва идентифицируем запросы, требующие доступа к данным интернет-магазина в режиме реального времени, например, списки недавно просмотренных товаров. Основная цель здесь — сохранить данные, требуемые службой запросов, в денормализованном формате, чтобы обеспечить быстрый поиск. Материализованные представления денормализованы и оптимизированы для конкретного запроса или представления в пользовательском интерфейсе, чтобы быстрее и эффективнее извлекать данные. Материализованные представления могут быть созданы с использованием баз данных или специализированных систем кэширования. Чтобы получать обновления в режиме реального времени и поддерживать согласованность этих данных, подписавшись на изменения состояния баз других микросервисов, целесообразно использовать потоковую СУБД, например, Rockset, Materialise, RisingWave и DeltaStream. Подробнее о потоковых базах данных, которые поддерживают аналитические операции с непрерывными потоками данных в реальном времени с помощью SQL-запросов, мы писали здесь и здесь.
Потоковая СУБД может принимать данные в режиме реального времени из различных источников в виде потоков событий с помощью CDC-процесса и встроенного коннектора. Потоковая база данных создает материализованное представление, объединяя потоки событий вместе, и поддерживает актуальность представления по мере поступления новых событий обновления, добавления и удаления данных. Например, когда новый товар добавляется в каталог, соответствующее событие фиксируется и используется для обновления материализованного представления списков товаров, гарантируя актуальность и согласованность данных.
Возвращаясь к паттерну CQRS, который предполагает разделение команд и запросов, следует добавить микросервис, который будет обслуживать запросы на чтение, поступающие из пользовательского интерфейса клиентского приложения. Эти запросы API преобразуются в SQL-запросы, которые извлекают данные из материализованных представлений потоковой базы. Например, когда пользователь ищет товар, результаты поиска можно получить из материализованного представления для списков поиска, вместо того чтобы выполнять несколько вызовов API к различным микросервисам.
Таким образом, материализованные представления упрощают логику запросов, заранее агрегируя данные, избавляя разработчика от работы со сложными SQL-запросами со множеством JOIN-операторов. Благодаря оптимизации материализованных представлений под конкретные запросы, можно снизить нагрузку на основную базу данных и повысить общую производительность системы. Материализованные представления в потоковой базе данных могут предоставлять данные в режиме реального времени из нескольких микросервисов, реализуя шаблон CQRS. Разделение операций чтения и записи с предварительным вычислением представления данных также обеспечивает масштабируемость и отказоустойчивость. Потоковая база может быть развернута независимо от основной, что соответствует горизонтальному масштабированию запросов. Наконец, базу данных потоковой передачи можно использовать в качестве резерва на случай, если основная база выйдет из строя.
Узнайте больше подробностей по проектированию и поддержке современных дата-архитектур в проектах аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
Источники