Шаблоны проектирования для баз данных

Существуют различные шаблоны проектирования облачных сервисов. Про тот же Sidecar или Ambassador, я думаю, слышали многие. Шаблоны предназначены для решения определенных задач и те два шаблона, о которых речь пойдет в сегодняшней статье, тоже нужны для конкретной задачи — работы с базами данных.

СУБД является неотъемлемой частью хоть сколько‑нибудь серьезного современного приложения. Соответственно, при проектировании приложения может возникнуть вопрос, как лучше сервисам взаимодействовать с базой данных: предоставляя общий доступ к одной базе или же у каждого микросервиса должна быть своя база данных. Мы рассмотрим два шаблона, предназначенных для решения данной задачи — это Shared database и Database per Microservice. Начнем с Shared database.

Общая база

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

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

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

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

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

В качестве решения перечисленных выше проблем можно использовать Shared базу данных для нескольких сервисов с общей структурой данных. При таком подходе каждый сервис будет иметь свободный доступ к данным, принадлежащим другим сервисам, с помощью локальных транзакций по правилу ACID (атомарность, согласованность, изоляция, устойчивость).

b81541c644b6bc6850b2ae5f94a816e3.png

Посмотрим, как можно реализовать Shared DB паттерн на практике. Сервисы TicketService и UserService имеют доступ к таблицам друг друга. Например, TicketService можно использовать следующую транзакцию ACID, чтобы гарантировать, что новый заказ не нарушит кредитный лимит клиента:

BEGIN TRANSACTION

…

SELECT TICKET_TOTAL

 FROM TICKETS WHERE USER_ID = ?

…

SELECT CREDIT_LIMIT

FROM USERS WHERE USER_ID = ?

…

INSERT INTO TICKETS …

…

COMMIT TRANSACTION

Как и у всех других паттернов, здесь также есть свои преимущества и недостатки, и соответственно, ситуации, когда предпочтительнее их использовать.

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

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

Помимо этого, так как все сервисы обращаются к одной и той же базе данных, они потенциально могут мешать друг другу. Например, если длительная UserService транзакция удерживает блокировку таблицы TICKET, она TicketService будет заблокирована.

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

В качестве альтернативы шаблону Shared DB выступает Database per service.

Каждому сервису по базе

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

Основная идея шаблона Database per service заключается в том, что — микросервисы не имеют доступа к базе соседних сервисов и обращаются между собой посредством REST, или через брокер сообщений. Таким образом наши микросервисы становятся действительно независимыми от хранилища и могут разрабатываться параллельно.

e12c8ec0c4b30edc88a6996a37d2499c.png

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

Так наши сервисы могут использовать те СУБД, которые для них лучше всего подходят. Например один сервис может использовать Elastic поиск, второй NoSQL, третий SQL, если этого требует бизнес логика.

Основные недостатки данный шаблон наследует от идеологии самой микросервисной архитектуры. Так, реализация бизнес‑транзакций, охватывающих несколько сервисов, является непростой задачей, требующей отдельной проработки. И внесение изменений в логику запросов также требует проработки.

Также у нас возникают сложности с управлением несколькими базами данных в нашем приложении. Например, если используются PostgreSQL, NoSQL и Elastic, то нам потребуются специалисты, знакомые со всеми этими БД.

Заключение

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

Больше актуальных навыков по архитектуре приложений вы можете получить в рамках практических онлайн‑курсов от экспертов отрасли.

© Habrahabr.ru