Оглавление

  1. Введение в System Design и работа с требованиями
  2. Моделирование систем (UML)
  3. CAP-теорема: Фундаментальные ограничения
  4. Балансировка нагрузки и CDN
  5. Кэширование: Стратегии и Инвалидация
  6. Масштабирование баз данных
  7. Порождение идентификаторов в распределенных системах
  8. Паттерны асинхронного взаимодействия (Bus)
  9. Распределенные паттерны: Event Sourcing и Saga
  10. Consistent Hashing (Согласованное хэширование)

1. Введение в System Design и работа с требованиями

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

Работа с требованиями

  • Функциональные требования (ФТ): Что система должна делать.
    • Необходимо выявлять истинную проблему бизнеса, а не просто реализовывать “как” просит заказчик.
    • Ubiquitous Language (Единый язык): Создание словаря терминов, понятного и бизнесу, и разработке.
    • Event Storming: Методика анализа процессов через события (event), команды (command) и действующих лиц (actors).
  • Нефункциональные требования (НФТ): Как система должна работать (атрибуты качества).
    • Производительность, масштабируемость, надежность, наблюдаемость.
  • Уровни обслуживания (SRE-подход):
    • SLI (Indicator): Метрика (например, время ответа).
    • SLO (Objective): Внутренняя цель (99.9% запросов < 200мс).
    • SLA (Agreement): Юридическое обязательство перед клиентом.

Физические ограничения

  • Сетевые и дисковые операции на порядки медленнее операций в памяти.
  • Пример: Чтение из L1 кэша (~0.5 нс) против сетевого запроса в другой дата-центр (~150 мс).

2. Моделирование систем (UML)

Для однозначного описания архитектуры используются визуальные модели:

  • Sequence Diagrams (Диаграммы последовательности): Взаимодействие объектов во времени.
  • Class Diagrams (Диаграммы классов): Статическая структура и отношения (композиция, агрегация).
  • State Diagrams (Диаграммы состояний): Жизненный цикл объекта и переходы.

3. CAP-теорема: Фундаментальные ограничения

В распределенной системе невозможно одновременно обеспечить более двух свойств из трех:

  1. Consistency (Согласованность): Все узлы видят одинаковые данные одновременно.
  2. Availability (Доступность): Каждый запрос получает ответ (успешный или нет).
  3. Partition Tolerance (Устойчивость к разделению): Система работает при разрыве связи между узлами.

Ключевой выбор: Поскольку сетевые сбои (P) неизбежны, мы выбираем между:

  • CP (Consistency + Partition Tolerance): Жертвуем доступностью ради точности (Zookeeper, MongoDB).
  • AP (Availability + Partition Tolerance): Жертвует согласованностью ради доступности (Cassandra, DynamoDB). Обеспечивают Eventual Consistency.

4. Балансировка нагрузки и CDN

Виды масштабирования

  • Вертикальное (Scale Up): Наращивание ресурсов одного сервера (имеет предел).
  • Горизонтальное (Scale Out): Добавление новых серверов.

Подходы к балансировке

  • На клиенте: Клиент получает список адресов через Service Discovery.
  • На сервере (Load Balancer): Прокси-узел (Nginx, HAProxy) распределяет трафик.
    • Алгоритмы: Round Robin, Weighted RR, Least Connections, Sticky Sessions.
  • CDN (Content Delivery Network): Сеть PoP-узлов (Points of Presence) для доставки статики из ближайшей к пользователю географической точки.

5. Кэширование: Стратегии и Инвалидация

Ключевые метрики

  • Cache Hit / Miss: Попадание или промах мимо кэша.
  • Hit Ratio: Отношение попаданий к общему числу запросов.

Стратегии чтения и записи

  • Read Through: Если данных нет в кэше, приложение само идет в БД, обновляет кэш и возвращает ответ.
  • Write Through: Данные пишутся одновременно в кэш и в БД.
  • Write Back (Отложенная запись): Данные пишутся только в кэш, а в БД попадают асинхронно (риск потери данных при сбое).

Инвалидация (вытеснение)

  • TTL (Time To Live): Удаление по времени.
  • LRU (Least Recently Used): Удаление давно не использовавшихся данных.
  • Cache Stampede: Проблема, когда при истечении кэша множество клиентов одновременно бьют в БД.

6. Масштабирование баз данных

Репликация

Копирование данных между узлами для отказоустойчивости.

  • Master-Slave: Мастер принимает запись, Slave — только чтение.
  • Синхронная: Мастер ждет подтверждения от Slave (высокая консистентность, медленная запись).
  • Асинхронная: Мастер подтверждает запись сразу (возможна потеря данных при сбое мастера).

Партиционирование (Секционирование)

Разбиение таблицы на части внутри одного сервера.

  • Цель: Ускорение запросов и удобство обслуживания (удаление старых партиций).

Шардирование

Горизонтальное разделение данных между разными серверами.

  • Вертикальное: Разные колонки на разных серверах.
  • Горизонтальное: Разные строки на разных серверах по ключу шардирования.
  • Минусы: Нет JOIN-ов между шардами, сложность транзакций.

7. Порождение идентификаторов в распределенных системах

В распределенных (шардированных) системах AUTO_INCREMENT не работает.

  • UUID (v4/v7): Децентрализовано, но v4 не упорядочен (плохо для индексов).
  • Snowflake ID (Twitter): 64-битный ID (Timestamp + Machine ID + Sequence). Глобально упорядочен.
  • Sequence + Shard ID: Использование локального сиквенса шарда с добавлением ID самого шарда.

8. Паттерны асинхронного взаимодействия (Bus)

Используются для построения слабосвязанных систем и достижения Eventual Consistency.

  • Event Bus (Шина событий): Уведомление “что-то произошло” (OrderCreated). Подписчик сам идет за деталями.
  • Command Bus (Шина команд): Приказ “сделай это” (CreateOrder). Содержит все данные для выполнения.
  • Data Bus (Шина данных): Передача полного состояния объекта для репликации или кэширования.

9. Распределенные паттерны: Event Sourcing и Saga

Event Sourcing

Хранение не состояния, а неизменяемого лога событий.

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

Saga

Управление транзакциями между микросервисами через последовательность локальных транзакций.

  • Хореография: Сервисы обмениваются событиями без центрального узла.
  • Оркестрация: Центральный сервис управляет шагами и вызывает компенсирующие транзакции (откат) при сбоях.

10. Consistent Hashing (Согласованное хэширование)

Решает проблему решардинга.

  • При обычном hash(id) % N добавление нового узла заставляет перемещать почти все данные.
  • Согласованное хэширование размещает узлы и данные на виртуальном кольце. При добавлении/удалении узла перемещается в среднем лишь 1/N часть данных.

Примечание: “Часы проектирования экономят недели разработки”. Проектируйте системы с учетом возможности их горизонтального масштабирования и неизбежности сбоев (Failure is inevitable).