Должен ли каждый микросервис обладать своей собственной базой данных?

«Должен ли каждый микросервис обладать своей собственной базой данных?» — вопрос из категории Архитектура, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, это фундаментальный принцип микросервисной архитектуры (принцип владения базами данных). Каждый сервис должен управлять своей собственной схемой данных и иметь эксклюзивный доступ к своей БД. Прямой доступ к БД одного сервиса из другого — это антипаттерн.

Почему это критически важно:

  • Независимость развертывания и масштабирования: Сервис и его БД можно масштабировать независимо от других (например, PaymentService с PostgreSQL и ProductCatalogService с MongoDB).
  • Изоляция сбоев: Проблема в БД одного сервиса (например, блокировка) не "потопит" всю систему.
  • Технологический полиглотизм: Возможность выбрать наиболее подходящий тип хранилища (реляционная БД, документное, key-value и т.д.) для конкретной предметной области.
  • Четкие границы контекстов: Предотвращает создание "большой шаровой грязи" (Big Ball of Mud) на уровне данных.

Как сервисы обмениваются данными? Через четко определенные API (обычно асинхронные, например, через брокер сообщений).

// OrderService публикует событие о создании заказа
public class OrderCreatedEvent
{
    public int OrderId { get; set; }
    public decimal TotalAmount { get; set; }
    // ... другие данные, НЕ вся внутренняя структура заказа
}

// PaymentService подписывается на это событие и обрабатывает его,
// используя только свою локальную БД для платежей.
public class PaymentEventHandler
{
    public async Task Handle(OrderCreatedEvent @event)
    {
        // Создание записи о платеже в БД PaymentService
        var payment = new Payment(@event.OrderId, @event.TotalAmount);
        await _paymentRepository.AddAsync(payment);
    }
}

Исключения и компромиссы: В некоторых сценариях (отчетность, глобальный поиск, аналитика) используется шаблон CQRS с отдельным читаемым хранилищем (Read Model), которое синхронизируется через события, или Saga для управления распределенными транзакциями.