Какую архитектуру базы данных вы использовали в последнем проекте: одиночную (single) или кластерную?

Ответ

В последнем проекте использовалась кластерная архитектура базы данных на основе PostgreSQL с репликацией streaming replication (master-slave).

Цели и преимущества такого подхода:

  • Отказоустойчивость (High Availability): При сбое master-узла можно выполнить failover на одну из реплик.
  • Масштабирование чтения (Read Scaling): Нагрузка операций SELECT распределяется между репликами, разгружая master, который обрабатывает операции INSERT/UPDATE/DELETE.
  • Резервное копирование: Резервные копии можно создавать с реплик, не нагружая основной узел.

Реализация на уровне приложения (Spring Boot):

  1. Настройка двух источников данных:
    spring:
      datasource:
        master:
          url: jdbc:postgresql://master-host:5432/db
          username: admin
          password: master_pass
        replica:
          url: jdbc:postgresql://replica-host:5432/db
          username: reader
          password: replica_pass
          hikari:
            read-only: true # Важно для реплик
  2. Использование AbstractRoutingDataSource: Создаётся роутер, который определяет, к какому DataSource (master или replica) направить запрос, обычно на основе флага "только для чтения" в контексте транзакции (@Transactional(readOnly = true)).

Альтернативы: Для более сложных сценариев рассматривались решения вроде Citus (горизонтальное шардирование) или облачные managed-сервисы (Amazon RDS Multi-AZ, Google Cloud SQL с high-availability).

Ответ 18+ 🔞

Да ты посмотри, какая красота архитектурная развернулась в последнем проекте! База данных, сука, не просто какая-нибудь одинокая, всеми брошенная, а целый кластер PostgreSQL с репликацией по-взрослому — streaming replication, master-slave.

Зачем, спрашивается, этот цирк с конями? А вот зачем, блядь:

  • Чтобы не сдохнуть, если что (High Availability): Мастер-узел возьмёт и накроется медным тазом? Да похуй! Мы тут же, как хитрая жопа, сделаем failover на одну из его реплик, и пользователи даже не успеют моргнуть, сука.
  • Чтоб не захлебнуться чтением (Read Scaling): Все эти бесконечные SELECT-ы, которые пользователи гоняют, мы свалим на реплики. Пусть они там пашут, а мастер-узел, важный такой, пусть сосредоточится на серьёзных делах — INSERT, UPDATE, DELETE. Разделение труда, ёпта!
  • Для бэкапов, не напрягая главного: Резервные копии будем драть с реплик, чтобы основного узла по пустякам не дергать. Пусть спокойно работает, а не бздит, что его каждый час в архив пихают.

А как же это в приложении, на Spring Boot, воплотить? Да элементарно, Ватсон!

  1. Настраиваем два источника данных в application.yml, как два брата-близнеца, но с разными характерами:

    spring:
      datasource:
        master:
          url: jdbc:postgresql://master-host:5432/db
          username: admin
          password: master_pass
        replica:
          url: jdbc:postgresql://replica-host:5432/db
          username: reader
          password: replica_pass
          hikari:
            read-only: true # Это, бля, важно! Говорим пулу: "Ты, браток, только читай, не выёбывайся с записью".
  2. Запускаем роутер AbstractRoutingDataSource. Эта хитрая жопа смотрит на каждый запрос и решает: "Ага, транзакция помечена как @Transactional(readOnly = true) — значит, пошёл на реплику, читай себе. А если запись — тогда, дружок, держи путь на мастер, получай свои данные в сраку!"

Ну а если нам мало этого великолепия? Если аппетиты растут, как на дрожжах, то можно, конечно, замахнуться на Citus для шардирования по горизонтали или сдаться на милость облачным провайдерам с их managed-сервисами вроде Amazon RDS Multi-AZ. Но это уже, как говорится, совсем другая история, с другим бюджетом и другим уровнем головной боли, блядь.