Облачные вычисления

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 без полного распределённого трейсинга - какие метрики указывают на её наличие?

Связанные уроки

  • net-67-latency-numbers
Performance Tuning

0

1

Войти