Перейти к основному содержимому

Принципы проектирования систем: масштабируемость, надёжность и производительность

Проектирование систем — это процесс определения архитектуры, компонентов, модулей, интерфейсов и данных системы для удовлетворения заданных требований.

1. Сбор требований​

Перед проектированием любой системы критически важно понять ограничения:

  • Функциональные требования: Что система делает (например, «Пользователь может отправить сообщение»).
  • Нефункциональные требования: Как система работает (например, «Обрабатывать 10k RPS», «99.9% доступность», «Низкая задержка»).

2. Стратегии масштабирования​

Вертикальное масштабирование (Scaling Up)​

Увеличение мощности одной машины (больше CPU, RAM, SSD).

  • Плюсы: Просто, без архитектурных изменений.
  • Минусы: Ограничено аппаратными возможностями, дорого, единая точка отказа.

Горизонтальное масштабирование (Scaling Out)​

Добавление новых машин в пул и распределение нагрузки.

  • Плюсы: Практически неограниченный рост, высокая отказоустойчивость.
  • Минусы: Требует балансировщик нагрузки и усложняет архитектуру (распределённое состояние).

3. Масштабируемость баз данных​

  • Репликация: Копирование данных на несколько узлов (Master-Slave/Leader-Follower). Запись идёт в Master, чтение — из Slave.
  • Шардирование: Разделение данных по нескольким независимым серверам баз данных на основе ключа шардирования (например, User ID).
  • Партиционирование: Разделение больших таблиц на более мелкие логические части в пределах одного экземпляра базы данных.

4. Метрики производительности и закон Литтла​

  • Задержка (Latency): Время обработки одного запроса.
  • Пропускная способность (Throughput): Количество запросов, обработанных за единицу времени.
  • Конкурентность (Concurrency): Количество запросов, обрабатываемых одновременно.

Закон Литтла: Concurrency = Throughput × Latency. Если увеличивать количество параллельных запросов (конкурентность) без увеличения пропускной способности, задержка будет расти.

5. Паттерны отказоустойчивости​

Circuit Breaker​

Предотвращает каскадные отказы, «разрывая» соединение с неисправной зависимостью и возвращая быстрый fallback-ответ.

Back Pressure​

Система отклоняет новые запросы (например, HTTP 429), когда перегружена, вместо того чтобы позволять очередям расти бесконечно и приводить к аварии.

Идемпотентность​

Гарантирует, что несколько одинаковых запросов дают тот же эффект, что и один. Критически важна для повторных попыток при сбоях сети (например, платежи).

6. Снижение хвостовой задержки (P99)​

Хвостовая задержка — это высокая задержка, с которой сталкивается небольшой процент запросов.

  • Hedged Requests: Отправка одного и того же запроса на несколько реплик и использование первого полученного ответа.
  • Request Coalescing: Объединение одинаковых одновременных запросов в один вызов к бэкенду.
  • Jittering: Добавление случайных задержек к запланированным задачам для предотвращения проблемы «thundering herd».
  • Deadline Propagation: Передача максимального ограничения по времени всем подсервисам.

7. Распределённые транзакции​

  • 2PC (Two-Phase Commit): Синхронный, блокирующий, обеспечивает строгую согласованность, но плохо масштабируется.
  • Паттерн Saga: Последовательность локальных транзакций с компенсирующими действиями при сбоях. Обеспечивает конечную согласованность и высокую масштабируемость.
  • TCC (Try-Confirm-Cancel): Паттерн на основе резервирования, распространённый в финтехе.

8. Модели согласованности​

  • Строгая согласованность (Strong Consistency): Каждое чтение видит последнюю запись (например, банковские системы).
  • Конечная согласованность (Eventual Consistency): Реплики в конечном счёте придут к единому состоянию, но временно могут показывать устаревшие данные (например, лайки в социальных сетях).
  • Линеаризуемость (Linearizability): Операции выглядят мгновенными и упорядоченными.