← Назад к вопросам

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

3.0 Senior🔥 121 комментариев
#REST API и микросервисы#SOLID и паттерны проектирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Паттерны управления данными в микросервисной архитектуре

Этот вопрос касается фундаментального выбора между двумя противоположными подходами к организации данных в микросервисной архитектуре. Вопрос проверяет понимание trade-offs и сложности распределенных систем.

Стандартный подход: Database per Service

В современной микросервисной архитектуре каждый микросервис имеет свою базу данных:

Order Service    Payment Service    Inventory Service
     |                 |                    |
  PostgreSQL        MongoDB             PostgreSQL

Преимущества Database per Service:

  • Слабая связанность (loose coupling)
  • Каждый сервис выбирает оптимальную БД для своего use case
  • Независимый масштабирование каждого сервиса
  • Отказ одной БД не влияет на другие

Недостатки:

  • Сложность распределенных транзакций
  • Проблема с данными, разбросанными по разным БД
  • Необходимо использовать Saga паттерн для распределенных транзакций

Противоположный подход: Shared Database

Это тот самый паттерн, который противоположен Database per Service.

В Shared Database подходе все микросервисы (или группа сервисов) используют одну общую базу данных:

Order Service    Payment Service    Inventory Service
              \        |         /
               \       |        /
                Shared PostgreSQL

Почему это называется Shared Database?

// Order Service
public class OrderService {
    private final OrderRepository orderRepository;
    private final PaymentRepository paymentRepository;  // Прямой доступ!
    
    public void createOrder(Order order) {
        // Два сервиса пишут в одну БД
        orderRepository.save(order);
        // Order Service может напрямую менять Payment таблицу
    }
}

// Payment Service
public class PaymentService {
    private final PaymentRepository paymentRepository;
    private final OrderRepository orderRepository;  // И наоборот!
    
    public void processPayment(Payment payment) {
        // Может напрямую получить Order
        Order order = orderRepository.findById(payment.getOrderId());
        paymentRepository.save(payment);
    }
}

Преимущества Shared Database

  1. Простота ACID транзакций
@Transactional
public void processOrderWithPayment(Order order, Payment payment) {
    orderRepository.save(order);
    paymentRepository.save(payment);
    // Оба изменения в одной транзакции - либо оба, либо ничего
    // БД гарантирует консистентность
}
  1. Не нужен Saga паттерн
// Плохо - Database per Service (нужен Saga)
public void orderSaga(Order order) {
    // Step 1: Создать заказ
    orderService.createOrder(order);
    // Step 2: Если упало, откатить order
    // Step 3: Создать платеж
    paymentService.createPayment(order.getId());
    // Step 4: Если упало, откатить и заказ
    // Сложная логика откатов (compensation transactions)
}

// Хорошо - Shared Database (простая транзакция)
@Transactional
public void createOrderWithPayment(Order order, Payment payment) {
    order.setPaymentId(payment.getId());
    orderRepository.save(order);
    paymentRepository.save(payment);
    // ACID гарантирует консистентность
}
  1. Простые запросы через JOIN
// Shared Database - просто
@Query("""
    SELECT o FROM Order o 
    JOIN o.payment p 
    WHERE p.status = 'completed' 
    AND o.createdAt > :date
""")
List<Order> getCompletedOrdersAfter(LocalDateTime date);

// Database per Service - сложно
// Нужно несколько запросов:
// 1. Запрос в Payment Service
// 2. Собрать список payment ids
// 3. Запрос в Order Service
// 4. Соединить результаты (в памяти)
  1. Проще отлаживать
Shared Database:
Запустил SELECT * FROM orders, payments
Вижу все данные в одном месте - понял что случилось

Database per Service:
Нужно запускать запросы в 5 разных БД
Данные разбросаны - сложнее понять связи

Недостатки Shared Database

  1. Сильная связанность (tight coupling)
// Order Service зависит от Payment schema
public class Order {
    @JoinColumn(name = "payment_id")  // Payment таблица
    private Payment payment;
}

// Если Payment Service переделает schema, сломается Order Service!
  1. Невозможно независимо масштабировать БД
Если Payment Service получает 1000 запросов/сек
А Order Service 100 запросов/сек

В Shared Database:
- Нельзя отдельно масштабировать для Payment
- Обслуживаются одной БД
- Конфликты за ресурсы

В Database per Service:
- Каждый масштабируется независимо
  1. Отказ БД = отказ всех сервисов
Shared Database:
Если PostgreSQL упала - все микросервисы down

Database per Service:
Если Payment MongoDB упала - только Payment Service down
Order Service продолжает работать
  1. Изменения schema сложнее
-- Нужно координировать между командами
-- Order Service команда хочет добавить поле
-- Но это может конфликтовать с Payment Service

Когда использовать каждый подход

Database per Service (рекомендуется)

Условия:
- Настоящие микросервисы с разными командами
- Можно использовать разные БД (SQL, NoSQL, Graph)
- Готовы работать с распределенными транзакциями
- Требуется независимое масштабирование
- Команды разработки независимы

Примеры:
- Netflix
- Amazon
- Uber

Shared Database (legacy, обучение)

Условия:
- Переходящая фаза от monolith к микросервисам
- Один владелец все данных (одна команда)
- Процесс только обучение микросервисам
- Мало микросервисов (2-3)
- Не нужно независимое масштабирование

Примеры:
- Migrating from monolith
- Team не готова к Saga паттернам

Гибридный подход

На практике часто используется КОМБИНАЦИЯ:

Public API Service (Shared Database)
   ├── User Service (собственная БД)
   ├── Order Service (собственная БД)
   └── Payment Service (собственная БД)


Логика:
- API Service с shared БД для быстрых cross-service queries
- Остальные с независимыми БД для масштабирования

Практический пример: Amazon

Rекомендация:
- Database per Service (каждый микросервис своя БД)

Чтобы синхронизировать данные между сервисами:
- Event Sourcing (все изменения - события)
- CQRS (отдельные модели для чтения и записи)
- Message Queues (RabbitMQ, Kafka)
- API Calls (один сервис вызывает API другого)

Это сложнее, чем Shared Database, но масштабируется на миллионы пользователей

Итог

Противоположный подход к Database per Service — это Shared Database паттерн.

Выбор между ними зависит от стадии развития системы и требований:

ПараметрDatabase per ServiceShared Database
МасштабируемостьОтличнаяПлохая
ТрансакцииСложные (Saga)Простые (ACID)
СвязанностьСлабаяСильная
СложностьВысокаяНизкая
РекомендуетсяДля productionДля обучения

Мой совет: начни с Database per Service, но будь готов к Saga паттернам и eventual consistency.

Какой знаешь паттерн, противоположный паттерну выделения отдельной базы данных каждому микросервису? | PrepBro