Облачные вычисления
Performance Tuning
Twitter хранит 100M+ timeline'ов в Redis - ответ за 1ms. Netflix обнаружила N+1 проблему через X-Ray: 1 GraphQL запрос -> 500 DB запросов. Profiling нашёл то, что code review пропустил.
- **Twitter:** Fan-out on write: новый твит -> запись в Redis Sorted Set для всех 100M+ followers одновременно. Читать timeline = 1 Redis ZRANGE запрос за <1ms вместо сложного JOIN.
- **Shopify:** PgBouncer Transaction mode для всей платформы. 10K одновременных Ruby on Rails connections -> 25 реальных PostgreSQL connections. Black Friday: пиковая нагрузка без деградации БД.
- **Netflix:** X-Ray distributed tracing выявил: один API вызов генерировал 47 downstream запросов. DataLoader-паттерн снизил до 3. Latency p99 упала с 800ms до 120ms без изменений инфраструктуры.
Caching
Кеширование - снижение нагрузки на базы данных и downstream сервисы через хранение результатов в быстром хранилище. Amazon ElastiCache (Redis/Memcached), AWS DAX (DynamoDB Accelerator), CloudFront CDN кеш. Паттерны: Cache-Aside (read через cache, miss -> DB -> cache), Write-Through (запись одновременно в cache и DB), Write-Behind (запись в cache, async в DB). Twitter: Redis кластер для 100M+ timeline'ов пользователей.
Redis vs Memcached: Redis поддерживает структуры данных (Sorted Sets, Hashes, Lists), персистентность, репликацию, Lua скрипты, Pub/Sub. Memcached: простое key-value, горизонтальное масштабирование через sharding, нет персистентности. Для большинства случаев Redis предпочтителен. ElastiCache Serverless (2023) - авто-масштабирование без управления нодами.
Cache Stampede (thundering herd) происходит когда:
Connection Pooling
PostgreSQL создание TCP соединения занимает 5-50ms + fork процесса. При 1000 req/sec без pooling: тысячи одновременных соединений убивают БД (лимит ~100-500 connections). PgBouncer - connection pooler для PostgreSQL. Режимы: Session (1:1), Transaction (connection возвращается после транзакции, рекомендуется), Statement (после каждого запроса). Supabase, Railway, Heroku используют PgBouncer по умолчанию.
Serverless + PostgreSQL проблема: Lambda/Edge Functions создают тысячи connections. Решения: PgBouncer на EC2 перед RDS, Amazon RDS Proxy (managed PgBouncer, интегрирован с IAM auth), Neon serverless driver (HTTP-based, без TCP connection), PlanetScale (MySQL over HTTP).
Почему PgBouncer Transaction mode несовместим с PostgreSQL PREPARE statements?
Async
Асинхронные паттерны снижают latency и повышают throughput. Параллельные запросы вместо sequential: Promise.all вместо await в цикле. Offloading тяжёлых операций в фоновые очереди (SQS, BullMQ): HTTP ответ 202 Accepted мгновенно, обработка асинхронно. Read-after-write consistency: возвращать данные из запроса/кеша вместо немедленного re-read из слейва.
N+1 проблема в ORM: запрос списка пользователей + по запросу для каждого профиля. Решение: DataLoader (batching + deduplication) для GraphQL, Prisma include для SQL JOIN, SELECT IN вместо цикличных запросов. Prisma findMany с include = один JOIN запрос.
DataLoader решает N+1 проблему в GraphQL через:
Profiling
Профилирование выявляет реальные bottleneck'и - не интуитивные. AWS X-Ray: distributed tracing для Lambda, ECS, EC2. CloudWatch Container Insights: CPU/Memory для EKS/ECS. RDS Performance Insights: топ SQL запросы по wait events. pg_stat_statements: статистика выполнения всех запросов PostgreSQL. Node.js --prof + clinic.js для CPU/Memory профилирования.
EXPLAIN ANALYZE в PostgreSQL - незаменимый инструмент оптимизации запросов. Seq Scan на большой таблице = нет индекса. Hash Join vs Nested Loop: optimizer выбирает, но explain покажет если выбор неоптимален. pgBadger анализирует PostgreSQL логи и находит медленные запросы автоматически.
Что означает 'Seq Scan' в EXPLAIN ANALYZE вместо 'Index Scan' для большой таблицы?
Итоги
- **Caching:** Cache-Aside + stale-while-revalidate для баланса freshness/speed. Cache Stampede решается mutex или probabilistic expiration. Redis Sorted Sets для leaderboards и time-series.
- **Connection Pooling:** PgBouncer Transaction mode для 10K -> 25 connections. Lambda + RDS Proxy или Neon serverless driver. Отключить PREPARE statements с pgbouncer=true.
- **Async + Profiling:** DataLoader batching решает N+1. Promise.all для параллельных запросов. EXPLAIN ANALYZE + pg_stat_statements для SQL bottlenecks. X-Ray для distributed tracing.
Связанные темы
Performance Tuning охватывает несколько уровней стека:
- Amazon ElastiCache и Redis — ElastiCache для Redis - managed кластер с автоматическими патчами, Multi-AZ, Cluster Mode для горизонтального масштабирования. ElastiCache Serverless авто-масштабирует без управления нодами
- RDS и Aurora оптимизация — Aurora Read Replicas для read scaling, RDS Performance Insights для wait event анализа, Aurora Serverless v2 для переменной нагрузки без over-provisioning
- CDN и Edge Cache — CloudFront кеширует не только статику - API ответы с Cache-Control headers. s-maxage + stale-while-revalidate снимает нагрузку с origin при пиках
Вопросы для размышления
- Как выбрать оптимальный TTL для кеша пользовательских данных с учётом trade-off между freshness и нагрузкой на БД?
- При каком количестве одновременных Lambda invocations PgBouncer перестаёт справляться и нужен RDS Proxy?
- Как найти N+1 проблему в production без полного распределённого трейсинга - какие метрики указывают на её наличие?