9. Продвинутые темы (middle+ → senior)
Разбор возможностей уровня прикладной архитектуры: Change Streams для событий в реальном времени, мультидокументные транзакции, топологии несколько регионов, выбор Atlas vs self-hosted, скетчи автоматизации (Ansible, Terraform). Акцент на ограничениях и практике production.
Change Streams
Поток изменений на уровне коллекции или БД: приложение подписывается и получает события insert / update / replace / delete (и др.) из oplog, без внешнего poll’инга всей коллекции.
Когда уместно: синхронизация с поисковым индексом, кэшем, audit trail, интеграции «в реальном времени» при идемпотентном потребителе.
Ограничения и best practices:
| Аспект | Комментарий |
|---|---|
| Доступность | На primary; при failover поток прерывается — драйвер переподключается, нужен resume token |
| Нагрузка | Большой поток изменений → выше нагрузка на replication; фильтруйте $match |
| Идемпотентность | Повтор доставки возможен; потребитель не должен ломаться от дубликатов |
Пример (mongosh)
// Подписка только на вставки в shop.orders (иллюстрация; в приложении — драйвер + async цикл)
const pipeline = [{ $match: { operationType: "insert" } }]
const options = { fullDocument: "updateLookup" }
const stream = db.orders.watch(pipeline, options)
// В скрипте: stream.hasNext() / stream.next() пока нужно
// Реальное приложение хранит resumeAfter / startAfter после рестарта
Production: используйте startAfter / resumeAfter из последнего токена; тестируйте поведение при выборах primary и длинном простое consumer’а.
Транзакции (multi-document)
С MongoDB 4.0+ на replica set доступны ACID-транзакции между несколькими документами/коллекциями в одной сессии. По умолчанию транзакции короткие; долгие удерживают ресурсы и повышают риск конфликтов (TransientTransactionError, UnknownTransactionCommitResult).
Best practices:
- По возможности проектируйте атомарность на уровне документа (
updateс вложенными массивами) — проще и быстрее. - Транзакции — когда нужна согласованность между несколькими документами и это оправдано сметой latency.
writeConcern: "majority"для коммита при необходимости устойчивости (согласуйте с продуктом).- Обрабатывайте retry коммита по документации драйвера.
Пример логики (mongosh-стиль)
const session = db.getMongo().startSession()
session.startTransaction({
readConcern: { level: "snapshot" },
writeConcern: { w: "majority", j: true },
})
try {
db.orders.insertOne({ _id: "ORD-1", status: "pending" }, { session })
db.inventory.updateOne({ sku: "A" }, { $inc: { qty: -1 } }, { session })
session.commitTransaction()
} catch (e) {
session.abortTransaction()
throw e
} finally {
session.endSession()
}
На sharded cluster транзакции поддерживаются (см. ограничения версии); проверяйте документацию под вашу версию.
Мультирегионные кластеры
Типичные цели: DR (аварийное переключение в другой регион), чтение ближе к пользователю, юридическое хранение данных в регионе.
| Идея | Комментарий |
|---|---|
| Replica set в нескольких досягаемостях | Priority и votes задают предпочтительного primary; избегайте split-brain при потере связи между сайтами |
| Latency записи | Запись идёт в primary; «удалённый» primary дороже по RTT |
| Zones | Правила размещения members/shards по регионам и зонам |
| Read preferences | nearest / региональные вторичные — со сдвигом консистентности |
Production: моделировать PARTITION сети заранее; согласовать RPO/RTO; для глобальных схем часто смотрят MongoDB Atlas (Global Writes / региональные кластеры) или тщательно спроектированный self-hosted.
Atlas vs self-hosted
| Критерий | Atlas (managed) | Self-hosted |
|---|---|---|
| Операции | Патчи, бэкапы, масштаб — в продукте | Всё на команде: K8s/VM, мониторинг, DR |
| Сетевая модель | VPC peering, Private Endpoint | Полный контроль, больше ответственности |
| Стоимость | Предсказуемый Opex по тарифу | CapEx + зарплата инженеров |
| Compliance | Сертификации облака | Контур заказчика |
| Гибкость | Ограничения версии/фич облака | Любые плагины/тонкая настройка при компетенции |
Best practice: Atlas — когда нужно ускорить time-to-market и снять рутину; self-hosted — жёсткие on-prem требования, нестандартная среда или экономия на масштабе при зрелой платформе.
Автоматизация: Ansible и Terraform
Ansible
- Модули/роли для установки пакетов, раскладки
mongod.conf,keyFile, systemd, создания пользователей (кускиmongodb_userв коллекции и т.д. — по коллекцииcommunity.mongodb). - Идемпотентность: повторный прогон не должен ломать кластер.
# Идея play: шаблон mongod.conf + перезапуск handler
- name: Deploy mongod config
ansible.builtin.template:
src: mongod.conf.j2
dest: /etc/mongod.conf
notify: Restart mongod
Terraform
- MongoDB Atlas Provider: проекты, кластеры, IP access list, пользователи БД как код.
- Альтернатива: Terraform для инфраструктуры (VPC, K8s) + Helm/оператор для MongoDB внутри кластера.
# Иллюстрация: провайдер atlas (имена ресурсов зависят от версии провайдера)
terraform {
required_providers {
mongodbatlas = {
source = "mongodb/mongodbatlas"
}
}
}
# resource "mongodbatlas_project" "shop" { ... }
# resource "mongodbatlas_cluster" "main" { ... }
Production: секреты через Vault / TF Cloud variables; state с блокировкой; изменения кластера только через pipeline, не руками в обход Iac.
Краткий чеклист
| # | Практика |
|---|---|
| 1 | Change Streams — resume token, устойчивость к failover |
| 2 | Транзакции — короткие, retry, по возможности модель без них |
| 3 | Мультирегион — выборы, priority, зоны и сетевой PARTITION план |
| 4 | Atlas vs self-hosted — решение зафиксировать в ADR |
| 5 | Ansible/Terraform — не хранить пароли в репозитории |