Ответ
В последнем проекте использовалась кластерная архитектура базы данных на основе PostgreSQL с репликацией streaming replication (master-slave).
Цели и преимущества такого подхода:
- Отказоустойчивость (High Availability): При сбое master-узла можно выполнить failover на одну из реплик.
- Масштабирование чтения (Read Scaling): Нагрузка операций
SELECTраспределяется между репликами, разгружая master, который обрабатывает операцииINSERT/UPDATE/DELETE. - Резервное копирование: Резервные копии можно создавать с реплик, не нагружая основной узел.
Реализация на уровне приложения (Spring Boot):
- Настройка двух источников данных:
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 # Важно для реплик - Использование
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, воплотить? Да элементарно, Ватсон!
-
Настраиваем два источника данных в
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 # Это, бля, важно! Говорим пулу: "Ты, браток, только читай, не выёбывайся с записью". -
Запускаем роутер
AbstractRoutingDataSource. Эта хитрая жопа смотрит на каждый запрос и решает: "Ага, транзакция помечена как@Transactional(readOnly = true)— значит, пошёл на реплику, читай себе. А если запись — тогда, дружок, держи путь на мастер, получай свои данные в сраку!"
Ну а если нам мало этого великолепия? Если аппетиты растут, как на дрожжах, то можно, конечно, замахнуться на Citus для шардирования по горизонтали или сдаться на милость облачным провайдерам с их managed-сервисами вроде Amazon RDS Multi-AZ. Но это уже, как говорится, совсем другая история, с другим бюджетом и другим уровнем головной боли, блядь.