День: 01.02.2025

  • Памятка по системному дизайну

    Памятка по системному дизайну

    Выбор правильной архитектуры = Выбор правильных сражений + Управление компромиссами

    Перевод: https://gist.github.com/vasanthk/485d1c25737e8e72759f

    Основные шаги

    1. Уточнить и согласовать масштаб системы
    • Варианты использования (описание последовательностей событий, которые в совокупности приводят к полезному действию системы)
    • Кто будет использовать систему?
    • Как они будут ее использовать?
    1. Ограничения
    • В основном определите ограничения по обработке трафика и данных в масштабе.
    • Масштаб системы (запросы в секунду, типы запросов, объем записываемых данных в секунду, объем считываемых данных в секунду)
    • Особые системные требования, такие как многопоточность, ориентация на чтение или запись.
    1. Проектирование архитектуры высокого уровня (абстрактный дизайн)
    • Набросайте важные компоненты и связи между ними, не вдаваясь в детали.
    • Уровень сервиса приложений (обслуживает запросы)
    • Перечислите различные необходимые сервисы.
    • Уровень хранения данных
    • Например, масштабируемая система обычно включает веб-сервер (балансировщик нагрузки, load balancer), сервис (разделение сервисов, service partition), базу данных (кластер баз данных master/slave) и системы кэширования.
    1. Проектирование компонентов
    • Компоненты + конкретные API, необходимые для каждого из них.
    • Объектно-ориентированный дизайн для функциональности.
    • Сопоставление функций с модулями: один сценарий для одного модуля.
    • Рассмотрите отношения между модулями:
      • Некоторые функции должны иметь уникальный экземпляр (Одиночки, Singletons)
      • Основной объект может состоять из многих других объектов (композиция, composition)
      • Один объект является другим объектом (наследование, inheritance)
    • Проектирование схемы базы данных.
    1. Понимание узких мест
    • Возможно, вашей системе нужен балансировщик нагрузки и множество машин за ним для обработки пользовательских запросов.
    • Или, возможно, данных так много, что вам нужно распределить базу данных на несколько машин. Каковы некоторые недостатки, возникающие при этом?
    • Слишком ли медленная база данных и нуждается ли она в кэшировании в памяти?
    1. Масштабирование абстрактного дизайна
    • Вертикальное масштабирование (vertical scaling)
      • Масштабирование путем добавления большей мощности (CPU, RAM) к существующей машине.
    • Горизонтальное масштабирование (horizontal scaling)
      • Масштабирование путем добавления большего количества машин в пул ресурсов.

    Кэширование (Caching)

    Балансировка нагрузки помогает масштабироваться горизонтально на постоянно растущем числе серверов, но кэширование позволит вам гораздо эффективнее использовать уже имеющиеся ресурсы, а также сделает возможными иначе недостижимые требования к продукту.

    • Кэширование приложений требует явной интеграции в код приложения. Обычно оно проверяет, есть ли значение в кэше; если нет, извлекает значение из базы данных.
    • Кэширование базы данных, как правило, «бесплатно». Когда вы включаете базу данных, вы получаете некоторый уровень настройки по умолчанию, который обеспечит определенную степень кэширования и производительности.
    • Кэши в памяти (in-memory caches) наиболее мощны с точки зрения чистой производительности. Это потому, что они хранят весь набор данных в памяти, а доступ к RAM на порядки быстрее, чем к диску. Например, Memcached или Redis.

    Примеры:

    • Предварительный расчет результатов (например, количество посещений с каждого реферального домена за предыдущий день)
    • Предварительное создание дорогостоящих индексов (например, предлагаемые истории на основе истории кликов пользователя)
    • Хранение копий часто запрашиваемых данных в более быстром бэкенде (например, Memcache вместо PostgreSQL)

    Балансировка нагрузки (Load balancing)

    Публичные серверы масштабируемого веб-сервиса скрыты за балансировщиком нагрузки. Этот балансировщик нагрузки равномерно распределяет нагрузку (запросы от ваших пользователей) на вашу группу/кластер серверов приложений.

    Типы:

    • Умный клиент (трудно сделать идеально)
    • Аппаратные балансировщики нагрузки (дорого, но надежно)
    • Программные балансировщики нагрузки (гибридные — подходят для большинства систем)

    Репликация базы данных (Database replication)

    Репликация базы данных — это частое электронное копирование данных из базы данных на одном компьютере или сервере в базу данных на другом, чтобы все пользователи имели доступ к одному уровню информации. Результатом является распределенная база данных, в которой пользователи могут получить доступ к данным, относящимся к их задачам, не мешая работе других. Реализация репликации базы данных с целью устранения неоднозначности или несогласованности данных между пользователями известна как нормализация.

    Партиционирование базы данных (Database partitioning)

    Партиционирование реляционных данных обычно относится к разложению ваших таблиц либо по строкам (горизонтально), либо по столбцам (вертикально).

    Map-Reduce

    Для достаточно небольших систем вы часто можете обойтись специальными запросами к SQL-базе данных, но этот подход может не масштабироваться тривиально, когда количество хранимых данных или нагрузка на запись требует шардинга вашей базы данных, и обычно требует выделенных подчиненных узлов для выполнения этих запросов (в этот момент, возможно, вы предпочтете использовать систему, разработанную для анализа больших объемов данных, вместо борьбы с вашей базой данных).

    Добавление слоя map-reduce позволяет выполнять интенсивные операции с данными и/или обработкой за разумное время. Вы можете использовать его для расчета предлагаемых пользователей в социальном графе или для создания аналитических отчетов. Например, Hadoop, и, возможно, Hive или HBase.

    Платформенный слой (Сервисы) (Platform Layer (Services))

    Разделение платформы и веб-приложения позволяет масштабировать части независимо. Если вы добавляете новый API, вы можете добавить серверы платформы без добавления ненужной мощности для уровня веб-приложения.

    Добавление платформенного слоя может быть способом повторного использования вашей инфраструктуры для нескольких продуктов или интерфейсов (веб-приложение, API, приложение для iPhone и т.д.) без написания слишком большого количества избыточного шаблонного кода для работы с кэшами, базами данных и т.д.

    Ключевые темы для проектирования системы

    1. Параллелизм (Concurrency)
    • Понимаете ли вы потоки, взаимоблокировку и голодание? Знаете ли вы, как распараллеливать алгоритмы? Понимаете ли вы согласованность и когерентность?
    1. Сетевое взаимодействие (Networking)
    • Примерно понимаете ли вы IPC и TCP/IP? Знаете ли вы разницу между пропускной способностью и задержкой, и когда каждый фактор является релевантным?
    1. Абстракция (Abstraction)
    • Вы должны понимать системы, на которых вы строите. Знаете ли вы примерно, как работают ОС, файловая система и база данных? Знаете ли вы о различных уровнях кэширования в современной ОС?
    1. Производительность в реальном мире (Real-World Performance)
    • Вы должны быть знакомы со скоростью всего, что может делать ваш компьютер, включая относительную производительность RAM, диска, SSD и вашей сети.
    1. Оценка (Estimation)
    • Оценка, особенно в форме приблизительного расчета, важна, потому что она помогает вам сузить список возможных решений только до тех, которые осуществимы. Тогда вам нужно написать только несколько прототипов или микро-бенчмарков.
    1. Доступность и надежность (Availability & Reliability)
    • Думаете ли вы о том, как вещи могут выйти из строя, особенно в распределенной среде? Знаете ли вы, как проектировать систему для борьбы с сетевыми сбоями? Понимаете ли вы долговечность?

    Соображения по проектированию системы веб-приложений:

    1. Безопасность (CORS)
    2. Использование CDN
    • Сеть доставки контента (CDN) — это система распределенных серверов (сеть), которая доставляет веб-страницы и другой веб-контент пользователю на основе географического расположения пользователя, происхождения веб-страницы и сервера доставки контента.
    • Эта услуга эффективна для ускорения доставки контента веб-сайтов с высоким трафиком и веб-сайтов с глобальным охватом. Чем ближе сервер CDN географически к пользователю, тем быстрее контент будет доставлен пользователю.
    • CDN также обеспечивают защиту от больших всплесков трафика.
    1. Полнотекстовый поиск (Full Text Search)
    • Использование Sphinx/Lucene/Solr — которые достигают быстрых поисковых ответов, потому что вместо прямого поиска по тексту они ищут по индексу.
    1. Автономная поддержка/Прогрессивное улучшение
    • Service Workers
    • Web Workers
    1. Серверный рендеринг (Server Side rendering)
    2. Асинхронная загрузка активов (Lazy load items)
    3. Минимизация сетевых запросов (Http2 + bundling/sprites и т.д.)
    4. Продуктивность разработчиков/Инструментарий
    5. Доступность (Accessibility)
    6. Интернационализация
    7. Отзывчивый дизайн (Responsive design)
    8. Совместимость браузеров

    Рабочие компоненты архитектуры фронтенда

    1. Код
    • HTML5/WAI-ARIA
    • Стандарты и организация кода CSS/Sass
    • Объектно-ориентированный подход (как объекты разбиваются и собираются вместе)
    • JS фреймворки/организация/техники оптимизации производительности
    1. Доставка активов — Фронтенд операции
    2. Документация
    • Документы по внедрению
    • Руководство по стилю/Библиотека шаблонов
    • Диаграммы архитектуры (поток кода, цепочка инструментов)
    1. Тестирование
    • Тестирование производительности
    • Визуальная регрессия
    • Модульное тестирование
    • Сквозное тестирование
    1. Процесс
    • Git Workflow
    • Управление зависимостями (npm, Bundler, Bower)
    • Системы сборки (Grunt/Gulp)
    • Процесс развертывания
    • Непрерывная интеграция (Travis CI, Jenkins)

  • План проведения интервью по системному дизайну

    План проведения интервью по системному дизайну

    Перевод репозитория https://leetcode.com/discuss/career/229177/My-System-Design-Template

    1. Ожидания от функционала [5 мин]

    • Варианты использования
    • Сценарии, которые не будут охвачены
    • Кто будет использовать
    • Сколько пользователей будет
    • Шаблоны использования

    2. Оценки [5 мин]

    • Пропускная способность (QPS для запросов на чтение и запись)
    • Ожидаемая латентность системы (для запросов на чтение и запись)
    • Соотношение чтения/записи
    • Оценки трафика
    • Запись (QPS, объем данных)
    • Чтение (QPS, объем данных)
    • Оценки хранилища
    • Оценки памяти
    • Какие данные мы хотим хранить в кэше, если используем его
    • Сколько RAM и машин нам нужно для достижения этого
    • Объем данных для хранения на диске/SSD

    3. Цели проектирования [5 мин]

    • Требования к латентности и пропускной способности
    • Согласованность vs Доступность [Слабая/сильная/итоговая => согласованность | Отказоустойчивость/репликация => доступность]

    4. Высокоуровневый дизайн [5-10 мин]

    • API для сценариев чтения/записи критических компонентов
    • Схема базы данных
    • Базовый алгоритм
    • Высокоуровневый дизайн для сценариев чтения/записи

    5. Глубокое погружение [15-20 мин]

    Масштабирование алгоритма

    Масштабирование отдельных компонентов:

    • Доступность, согласованность и масштабируемость для каждого компонента
    • Паттерны согласованности и доступности

    Рассмотрение следующих компонентов, их интеграции и пользы:

    a) DNS

    b) CDN [Push vs Pull]

    c) Балансировщики нагрузки [Активный-Пассивный, Активный-Активный, Уровень 4, Уровень 7]

    d) Обратный прокси

    e) Масштабирование уровня приложений [Микросервисы, Обнаружение сервисов]

    f) БД [RDBMS, NoSQL]

    • RDBMS
    • Мастер-слейв, Мастер-мастер, Федерация, Шардинг, Денормализация, Оптимизация SQL
    • NoSQL
    • Ключ-Значение, Широкая колонка, Граф, Документ
    • Быстрый поиск:
      • RAM [Ограниченный размер] => Redis, Memcached
      • AP [Неограниченный размер] => Cassandra, RIAK, Voldemort
      • CP [Неограниченный размер] => HBase, MongoDB, Couchbase, DynamoDB

    g) Кэши

    • Клиентское кэширование, CDN кэширование, Кэширование веб-сервера, Кэширование базы данных, Кэширование приложений, Кэш на уровне запросов, Кэш на уровне объектов
    • Политики вытеснения:
    • Cache aside
    • Write through
    • Write behind
    • Refresh ahead

    h) Асинхронность

    • Очереди сообщений
    • Очереди задач
    • Обратное давление

    i) Коммуникация

    • TCP
    • UDP
    • REST
    • RPC

    6. Обоснование [5 мин]

    • Пропускная способность каждого уровня
    • Латентность между каждым уровнем
    • Обоснование общей латентности
  • Числа, которые должен знать каждый разработчик

    Числа, которые должен знать каждый разработчик

    Времена доступа к памяти и хранилищам

    • Обращение к кэшу L1: 0.5 нс
    • Обращение к кэшу L2: 7 нс
    • Обращение к основной памяти: 100 нс
    • Чтение 1 МБ последовательно из основной памяти: 250,000 нс
    • Произвольный доступ к жесткому диску: 10,000,000 нс
    • Чтение 1 МБ последовательно с жесткого диска: 20,000,000 нс[3]

    Эти цифры показывают, насколько критична оптимизация работы с памятью и дисками для производительности программ.

    Сетевые задержки

    • Пересылка 2 КБ по сети со скоростью 1 Гбит/с: 20,000 нс
    • Передача сообщения туда/обратно в одном дата-центре: 500,000 нс
    • Передача пакета из Калифорнии в Нидерланды и обратно: 150,000,000 нс[3]

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

    Другие важные числа

    • Ошибка при предсказании условного перехода: 5 нс
    • Открытие/закрытие мьютекса: 25 нс
    • Сжатие 1 КБ быстрым алгоритмом: 3,000 нс[3]

    Эти цифры помогают оценивать эффективность различных операций в коде.

    Степени двойки

    Разработчикам также полезно помнить степени двойки: 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024[31]. Они часто встречаются при работе с памятью, файловыми системами и другими аспектами разработки.

    Коды ошибок HTTP

    • 403: доступ запрещен
    • 404: страница не найдена
    • 500: внутренняя ошибка сервера
    • 503: сервис недоступен[31]

  • План проектирования системы (System Design Outline)

    План проектирования системы (System Design Outline)

    Перевод и адаптация этого репозитория https://github.com/jguamie/system-design/blob/master/notes/system-design-outline.md

    Это рекомендуемый подход к решению задач проектирования систем. Не все эти темы будут актуальны для конкретной задачи.

    1. Функциональные требования / Уточнения / Предположения (Functional Requirements / Clarifications / Assumptions)
    2. Нефункциональные требования (Non-Functional Requirements)
      1. Согласованность vs Доступность (Consistency vs Availability)
      2. Задержка (Latency)
        1. Насколько быстрой должна быть эта система?
        2. Задержка, воспринимаемая пользователем (User-perceived latency)
        3. Задержка обработки данных (Data processing latency)
      3. Безопасность (Security)
        1. Потенциальные атаки? Как их следует смягчать?
      4. Конфиденциальность (Privacy)
        1. PII (Personally Identifiable Information — Персональные данные, позволяющие идентифицировать личность), PCI (Payment Card Industry — Индустрия платежных карт) или другие пользовательские данные
      5. Целостность данных (Data Integrity)
        1. Как восстановиться после повреждения или потери данных?
      6. Соотношение чтения:записи (Read:Write Ratio)
    3. API (Application Programming Interface — Интерфейс программирования приложений)
      1. Публичные и/или внутренние API?
      2. Просты ли API для понимания?
      3. Как идентифицируются сущности?
    4. Схемы хранения (Storage Schemas)
      1. SQL (Structured Query Language — Язык структурированных запросов) vs NoSQL (Not Only SQL — Не только SQL, обозначает нереляционные базы данных)
      2. Очереди сообщений (Message Queues)
    5. Проектирование системы (System Design)
    6. Масштабируемость (Scalability)
      1. Как масштабируется система? Учитывайте увеличение как объема данных, так и трафика.
      2. Каковы узкие места? Как их следует устранять?
      3. Каковы граничные случаи? Что может пойти не так? Предполагая, что они произойдут, как их следует решать?
      4. Как мы будем проводить стресс-тестирование этой системы?
      5. Балансировка нагрузки (Load Balancing)
      6. Автомасштабирование / Репликация (Auto-scaling / Replication)
      7. Кэширование (Caching)
      8. Партиционирование (Partitioning)
      9. Репликация (Replication)
      10. Непрерывность бизнеса и аварийное восстановление (BCDR — Business Continuity and Disaster Recovery)
      11. Интернационализация / Локализация (Internationalization / Localization)
        1. Как масштабироваться на несколько стран и языков? Не предполагайте, что в США используется только английский язык.