Инженерия ПО
Large-Scale Architecture
Цели урока
- Знать что Large-Scale Architecture решает: latency, throughput, availability, partition tolerance на масштабе миллиардов запросов
- Применять multi-region и cell-based архитектуру для отказоустойчивости
- Считать back-of-envelope: QPS, storage, bandwidth, cost при проектировании
- Различать tail latency (p99, p99.9) от средней - именно tail убивает UX
- Понимать почему Active-Active в трёх регионах дороже, но необходим для $-критичных систем
Предварительные знания
- Понимание базовых паттернов System Design (LB, кэш, реплика, шардирование)
- Знание CAP-теоремы и её следствий
- Опыт работы с любым облаком (AWS/GCP/Azure) хотя бы на уровне базовых сервисов
2006 год. Greg Linden из Amazon рассказывает на Стэнфордском докладе про внутренний A/B-эксперимент: задержка страницы на 100 мс роняет продажи на 1%. В тот год выручка Amazon была $10 млрд, то есть $100 млн потенциальных потерь от ленивой архитектуры. К 2023-му та же чувствительность даёт $5,7 млрд в год - именно поэтому миллиардеры покупают подсекундное latency. Large-Scale Architecture - про то, как обеспечить <100 мс для миллиарда пользователей одновременно.
- **Netflix** поддерживает Active-Active в трёх регионах AWS и регулярно проводит Chaos Engineering: инженеры отключают целый регион в рабочее время, чтобы убедиться что система выдержит реальную аварию
- **Shopify** обслуживает 10 000+ магазинов через Cell Architecture - каждый магазин изолирован, поэтому Black Friday одного крупного ритейлера не влияет на другие магазины
- **Stripe** обрабатывает $1+ трлн платежей в год с SLA 99.9999% (31 секунда downtime в год) - достигается через Cell Architecture + Multi-Region + строгий DR план
Cell Architecture
**Cell Architecture** (Shard-Nothing Architecture) - подход при котором система разбивается на независимые изолированные ячейки (cells/shards), каждая из которых обслуживает подмножество пользователей. Ячейка содержит полный стек: API серверы, базу данных, очереди. Сбой одной ячейки не влияет на остальные.
**Cell routing** - ключевая проблема: куда направить запрос пользователя? Варианты: 1) Consistent Hashing по user_id - детерминированный, не требует lookup. 2) Lookup Service (Redis/Cassandra) - гибкий, можно мигрировать пользователей между ячейками. 3) DNS-based - каждая ячейка на отдельном домене (tenant.company.com → cell). Shopify использует Lookup Service для возможности балансировки при росте магазина.
Граница ячейки - самая сложная архитектурная проблема: как обрабатывать операции, затрагивающие пользователей в разных ячейках? Stripe решает это через Global Services (fraud detection, payment routing) которые работают поверх всех ячеек. Данные, требующие глобальной координации, выносятся в отдельный глобальный tier.
Cell Architecture развёрнута из 4 ячеек. В ячейке 2 произошёл полный outage БД. Что происходит с пользователями?
Multi-Region Deployment
**Multi-Region** deployment означает работу системы из нескольких географических регионов одновременно. Мотивация двойная: latency (данные близко к пользователям) и availability (регион может выйти из строя). AWS предлагает 33 региона, каждый из 3+ Availability Zones (AZ).
**Data sovereignty** - критическая проблема Multi-Region: GDPR (Европа), CCPA (Калифорния), ФЗ-152 (Россия) требуют хранить данные граждан в конкретных регионах. Stripe сегрегирует данные EU-клиентов в европейском регионе. Это означает что Multi-Region не только про performance - иногда это юридическое требование.
Основная техническая сложность Active-Active - **conflict resolution**: что происходит если пользователь изменил профиль одновременно в US и EU? Решения: Last Write Wins (LWW) по timestamp - просто, но теряет данные. CRDT (Conflict-free Replicated Data Types) - автоматическое слияние без конфликтов. Region-based ownership - пользователь "принадлежит" региону, все его writes идут туда.
Компания выходит на рынок Европы. Пользователи в EU жалуются на latency 200ms. Основная причина:
Disaster Recovery
**Disaster Recovery (DR)** - набор политик и процедур для восстановления после катастрофических сбоев: пожар в датацентре, удаление данных оператором, природные катастрофы. DR планируется заранее и регулярно тестируется - непротестированный DR план не работает в момент X.
**DR Drill (Game Day)** - критически важная практика: система восстановления должна тестироваться регулярно. Netflix Chaos Monkey и DiRT (Disaster Recovery Testing) от Google проводят учения, имитируя реальные аварии. Типичный DR drill: отключить primary регион в scheduled time, зафиксировать фактический RTO, сравнить с целевым. Если фактический RTO > целевой - план дорабатывается.
GitLab в 2017 году случайно удалил production БД 300 GB. Из 5 резервных стратегий работала только одна (периодические бэкапы с задержкой 6 часов). Результат: 6 часов потери данных, 18 часов простоя. После инцидента GitLab полностью переработал DR план и сделал его публичным - один из лучших примеров blameless postmortem.
Финансовая система имеет RPO=5 минут и RTO=30 минут. Что это означает на практике?
Data Replication
**Data Replication** - процесс синхронизации данных между несколькими узлами. Это основа отказоустойчивости, масштабирования читающих запросов и Multi-Region deployment. Каждый режим репликации - трейдофф между consistency, latency и complexity.
**Replication lag** - время задержки между записью на leader и доступностью на replica. При асинхронной репликации lag может быть от миллисекунд до секунд. Это называется **Read-Your-Writes** проблема: пользователь обновил профиль, но при следующем запросе попал на отстающую реплику и видит старые данные. Решения: routing writes to leader для конкретного пользователя, sticky sessions, wait-for-replica при критических reads.
GitHub использует MySQL с Orchestrator для автоматического failover: при падении primary за 30 секунд выбирается новый leader из реплик. LinkedIn мигрировал с MySQL на Espresso (их Cassandra-based БД) именно для Multi-Region репликации - MySQL single-leader плохо масштабируется географически.
Репликация = резервное копирование. Если есть реплика, бэкапы не нужны
Репликация и бэкапы решают разные проблемы и нужны одновременно
Репликация защищает от hardware failure: нода упала - данные есть на реплике. Но репликация мгновенно распространяет любые изменения - включая случайное `DELETE FROM users WHERE 1=1`. Бэкап - это snapshot в прошлом, который позволяет восстановить данные до момента катастрофы. GitLab потерял данные именно потому что реплики были есть, но все они синхронно реплицировали удаление.
Cassandra настроена N=5, W=3, R=3. Можно ли прочитать актуальные данные сразу после записи?
Итоги
- **Cell Architecture** изолирует blast radius: сбой одной ячейки затрагивает только её пользователей, остальные продолжают работать
- **Multi-Region** решает две задачи: latency (данные ближе к пользователю) и availability (регион может выйти из строя); Active-Active требует conflict resolution
- **DR** определяется метриками RPO (допустимая потеря данных) и RTO (допустимое время простоя); непротестированный DR план не работает в момент аварии
- **Репликация** обеспечивает отказоустойчивость, но не заменяет бэкапы - удалённые данные реплицируются мгновенно на все узлы
Связанные темы
Large-Scale Architecture строится поверх фундаментальных концепций:
- Chaos Engineering — Game Days и fault injection - основной способ проверить что Cell Architecture и DR план работают до реальной аварии
- SRE и Error Budget — SLO определяет целевые RTO/RPO; error budget показывает сколько downtime допустимо при переключении регионов
- System Design Interview — Multi-Region и Cell Architecture - стандартные компоненты для задач типа "спроектируй систему на 1 млрд пользователей"
Вопросы для размышления
- Если бы датацентр с текущим проектом отключился прямо сейчас - сколько времени потребовалось бы на восстановление? Есть ли вообще DR план?
- Какой RPO приемлем для разных типов данных в проекте: пользовательские профили, транзакции, аналитика?
- Стоит ли Cell Architecture вложений для текущего масштаба, или это преждевременная оптимизация?