Инженерия ПО
Масштабирование систем
Black Friday 2020: Amazon обрабатывает 2.5 миллиона заказов в час в пик. За несколько часов до события тысячи инстансов добавляются автоматически через Auto Scaling. После - убираются. Стоимость горизонтального масштабирования: платишь только за используемые ресурсы в нужный момент, а не за постоянно стоящий idle мощный сервер.
- **Twitter Timeline**: хранит timeline в Redis кеш, обновляет при новых твитах (fanout-on-write). 1M запросов в секунду с latency < 1ms. Без кеша - NoSQL запросы к 300M followers
- **Stack Overflow**: 9 серверов для 50M пользователей. Агрессивное кеширование (Redis), эффективные SQL запросы. Горизонтальное масштабирование - не единственный путь
- **Netflix Auto Scaling**: в момент релиза популярного сериала трафик растёт в 10x за минуты. AWS Auto Scaling добавляет тысячи инстансов за минуты - без ручного вмешательства
Горизонтальное масштабирование
Горизонтальное масштабирование (Scale Out) - добавление новых инстансов (серверов, подов) вместо увеличения мощности существующих. Теоретически неограниченное: добавляй машины пока хватает денег. Netflix масштабирует от тысяч до десятков тысяч инстансов в AWS при пиках. Требование: приложение должно быть stateless - каждый инстанс может обработать любой запрос без зависимости от состояния других.
Stateless requirement: сессии не в памяти процесса - в Redis/Cookie. Загруженные файлы не на локальном диске - в S3/GCS. Кеш не локальный - в distributed cache. Горизонтальное масштабирование работает потому что нагрузка распределяется по инстансам через load balancer. При падении одного инстанса - остальные берут его нагрузку. Auto-scaling: Kubernetes HPA (Horizontal Pod Autoscaler) добавляет поды при CPU > 70%, убирает при снижении нагрузки.
Web-приложение хранит сессии пользователей в памяти процесса. При горизонтальном масштабировании до 3 инстансов пользователи постоянно выходят из системы. Почему?
Вертикальное масштабирование
Вертикальное масштабирование (Scale Up) - увеличение мощности существующего сервера: больше CPU, RAM, faster disk. Проще: не нужно менять архитектуру, приложение продолжает работать как есть. Но ограничено физически: самый мощный сервер AWS (u-24tb1.112xlarge) стоит $218/час и всё равно конечен. Также - single point of failure: один большой сервер упал = всё упало.
Когда vertical scaling оправдан: базы данных (горизонтальное масштабирование БД сложно - sharding, replication overhead), legacy monolithic приложения где рефакторинг под horizontal слишком дорог, быстрое временное решение пока идёт работа над horizontal. Правило: вертикальное масштабирование - хорошее начало, но горизонтальное нужно для истинного scale и reliability. Stack Overflow: один большой SQL Server на вертикальном scale обслуживает 50M пользователей.
PostgreSQL база данных стала bottleneck: CPU 95%, медленные запросы. Первый шаг для масштабирования?
Кеширование
Кеширование - хранение результатов дорогих вычислений или запросов для быстрого повторного использования. Иерархия кешей: L1 (CPU cache, nanoseconds), L2/L3 (nanoseconds), RAM (microseconds), SSD (milliseconds), Network (milliseconds-seconds). Redis - distributed in-memory cache, latency < 1ms. Twitter хранит Twitter feeds в Redis: 1M запросов в секунду с latency < 1ms вместо PostgreSQL запросов.
Стратегии инвалидации (самая сложная часть кеширования): TTL (Time To Live - данные устаревают через N секунд), Cache-Aside (приложение сначала проверяет кеш, при miss - запрашивает БД и кеширует), Write-Through (запись одновременно в кеш и БД), Write-Back (сначала в кеш, периодически сбрасывается в БД). Cache stampede: при истечении популярного ключа сотни запросов одновременно идут в БД. Решение: probabilistic early expiry или distributed lock.
Продукт обновился в БД. В Redis кеш-ключ product:123 с TTL 1 час. Пользователи видят старые данные. Как решить?
Load Balancing
Load Balancer распределяет трафик между инстансами. Алгоритмы: Round Robin (по очереди, простой), Weighted Round Robin (инстансы с разной мощностью), Least Connections (новый запрос на инстанс с наименьшим числом активных соединений), IP Hash (один пользователь всегда на один инстанс - для sticky sessions), Random. AWS ALB (Application Load Balancer) и NGINX - самые распространённые.
Health checks: load balancer периодически проверяет /health endpoint каждого инстанса. Если инстанс не отвечает - исключается из rotation. Graceful shutdown: при остановке инстанса (деплой) он сначала удаляется из rotation, ждёт завершения текущих запросов (drain), потом останавливается. Kubernetes readinessProbe отвечает за готовность принимать трафик, livenessProbe - жив ли процесс. Сочетание обоих позволяет zero-downtime deployment.
Кеширование всегда увеличивает производительность - чем больше кешируем, тем лучше
Кеширование создаёт сложность: инвалидация кеша - одна из двух сложных проблем в CS. Cache stampede, stale data, memory pressure - реальные проблемы. Кешировать нужно только там где измеримая проблема с производительностью
Phil Karlton: 'There are only two hard things in Computer Science: cache invalidation and naming things'. Без правильной инвалидации кеш становится источником багов с устаревшими данными
При деплое новой версии pod получает трафик сразу после старта. Первые запросы падают с 503 - приложение ещё не подключилось к БД. Как исправить?
Связанные темы
Масштабирование тесно связано с архитектурными решениями:
- Микросервисы: паттерны — Микросервисы позволяют масштабировать отдельные компоненты независимо - Payment Service отдельно от Catalog
- SRE: Site Reliability Engineering — SLO для throughput и latency - целевые метрики которые требуют правильного масштабирования для выполнения
Вопросы для размышления
- Горизонтальное масштабирование требует stateless архитектуры. Какие части современных веб-приложений сложнее всего сделать stateless?
- Caching invalidation - сложная проблема. Какая стратегия лучше подходит для продуктового каталога (редкие обновления) vs ленты новостей (частые обновления)?
- Когда вертикальное масштабирование предпочтительнее горизонтального несмотря на его ограничения?