System design Flashcards
Архитектуры ИС
- Файл-сервер - только извлекает данные из
файла или базы данных и передает их клиенту
для дальнейшей обработки - Клиент-сервер - извлекает данные из файла или
базы данных, обрабатывает и затем передает
результат клиенту - Peer-to-peer (P2P) - все узлы выполняют одинаковые
функции – нет централизованного
сервера
Уровни доступности (надежности) availability level
Надежность - система должна продолжать
работать корректно даже при
неблагоприятных обстоятельствах
Availability Level Average Yearly Downtime
Conventional Server 99% 87 hours, 40 minutes
Public Cloud Service 99.5% 43 hours, 50 minutes
99.9% 8 hours, 46 minutes
High-Availability Cluster 99.95% 4 hours, 23 minutes
Virtual Fault Tolerance 99.995% 26 minutes, 18 seconds
Continuous Availability 99.999% 5 minutes, 16 seconds
The Stratus Zone 99.9999% 31.6 seconds
SLA / SLO / SLI
- SLA (Service Level Agreement) – соглашение, которое вы заключаете со своими клиентами
- SLO (Service Level Objectives) - цели, которые команда должна решить, чтобы выполнить соглашение
- SLI (Service Lever Indicators) – показатели системы
Основные критерии систем
- Надежность
- Масштабируемость (вертикальное/горизонтальное)
- Производительность (Latency vs Response Time)
- Удобство сопровождения (observability/улучшение процессов/ополнительный инструментарий)
- Безопасность (сквозное/транспортное шифрование)
- Stateless and Statefull
Latency на чтение с разных типов дисков
- Read 1M from RAM = 250 000 нс
- Read 1M from SSD = 1 мс
- Read 1M from HDD = 20 мс
Low-latency приложения - такие приложение надо с самого начала писать с оптимизациями, с прямой ориентацией на low-latency. Подход, когда пишут сначала просто работающее приложение, а потом оптимизируют его, здесь не работает
Throughput (пропускная способность дисков)
- HDD = 200-300 МБ/с
- SSD = 600-700 МБ/с
- DDR3 = 17000 МБ/с
High-throughput приложения - приложения, заточенные под максимально возможную пропускную способность – latency в этом случае часто пренебрегают
Типы нагрузки
- Data intensive applications (DIA)
- Compute intensive applications (CIA)
- Read/Write ratio (read intensive/write intensive/realtime)
OLTP (online transaction processing)
OLAP (online analytics processing)
Микросервисы (плюсы/минусы)
Плюсы:
* Независимые релизы и разработка и быстрый CI/CD
* Независимая масштабируемость (только нужные сервисы)
* Независимая деградация (устойчивость к отказам)
* Технологическая свобода (возможность использовать разные технологии)
Минусы:
* Зоопарк технологий
* Сетевой вызов отвалится вероятнее, чем внутренний
* Распределенность и транзакционность
* Удаленные вызовы дороже локального исполнения
* Понимание всего контекста запроса
* Сложность тестирования всей системы
Плюсы:
✅ Гибкость и независимость – каждый сервис можно разрабатывать, тестировать и деплоить отдельно.
✅ Масштабируемость – можно масштабировать только нужные сервисы под нагрузку.
✅ Технологическая свобода – разные сервисы могут быть написаны на разных языках/фреймворках.
✅ Устойчивость к отказам – падение одного сервиса не всегда приводит к падению всей системы.
✅ Быстрый CI/CD – изменения в одном сервисе не требуют пересборки всей системы.
Минусы:
❌ Сложность разработки – нужно учитывать межсервисное взаимодействие (API, версионирование, ошибки).
❌ Распределенные транзакции – сложно обеспечить согласованность данных (нужны Saga, Event Sourcing и т. д.).
❌ Накладные расходы – сетевые задержки, сериализация/десериализация, нагрузка на Service Discovery.
❌ Сложность отладки – трассировка запросов между сервисами требует дополнительных инструментов (Jaeger, Zipkin).
❌ Оркестрация и DevOps – нужны Kubernetes, Docker, мониторинг, логирование, что усложняет инфраструктуру.
Монолит (плюсы/минусы)
Плюсы:
✅ Простота разработки – единая кодовая база, нет сложностей с межсервисным взаимодействием.
✅ Легкость тестирования – можно запускать интеграционные тесты без необходимости разворачивать множество сервисов.
✅ Простота деплоя – один артефакт (например, WAR/JAR-файл), который нужно развернуть.
✅ Согласованность транзакций – ACID-транзакции работают в рамках одной БД.
✅ Нет накладных расходов на межсервисную коммуникацию – все вызовы локальные.
Минусы:
❌ Масштабируемость – сложно масштабировать отдельные части системы, приходится масштабировать весь монолит.
❌ Гибкость технологий – сложно использовать разные языки/фреймворки для разных модулей.
❌ Риск “спагетти-кода” – при плохой архитектуре кодовая база быстро становится запутанной.
❌ Медленный CI/CD – даже при небольшом изменении нужно пересобирать и передеплоить весь монолит.
❌ Единая точка отказа – падение сервиса приводит к недоступности всей системы.
Монолит vs Микросервисы (что выбрать)
- Монолиты для стартапов и low-latency
- Микросервисы для всего остального
Балансировка нагрузки
- Клиентская
- Серверная
- Random
- Round Robin
- Weighted Round Robin
- Sticky Sessions (hash(user_id))
- Least Connections / Response Ttime / Bandwidth
- Power of two choices (Случайным образом выбираем два бэкенда из списка – из этих двух выбираем лучший по целевой метрике (least connections / sessions / …))
- L4 / L7 Балансировка
- DNS балансировка
- geoDNS балансировка
Проксирование (функции)
- Взлом / защита
- Кэширование данных
- Ограничения трафика
- Обход ограничений доступа
- Анонимность пользователей
- Сжатие и модификация данных
Типы прокси
- Forward Proxy
- Reverse Proxy
Forward Proxy
- Forward Proxy (Прямой прокси)
🔹 Расположение: На стороне клиента (или внутри его сети).
🔹 Назначение: Представляет интересы клиента при обращении к серверам в интернете.
🔹 Как работает:
Клиент настраивает свой трафик так, чтобы он шел через прокси.
Прокси делает запросы от имени клиента и возвращает ответ.
Плюсы:
✅ Анонимность – скрывает IP клиента от сервера.
✅ Обход блокировок – может использоваться для доступа к заблокированным ресурсам.
✅ Кэширование – ускоряет загрузку часто запрашиваемых данных.
✅ Контроль трафика – корпоративные прокси могут блокировать доступ к определенным сайтам.
Минусы:
❌ Замедление скорости (если прокси перегружен).
❌ Некоторые сайты блокируют известные прокси.
Примеры использования:
* Корпоративные сети (ограничение доступа сотрудников).
* VPN-сервисы (анонимизация трафика).
* Прокси для обхода географических блокировок.
Reverse Proxy
- Reverse Proxy (Обратный прокси)
🔹 Расположение: На стороне сервера (перед бекенд-серверами).
🔹 Назначение: Представляет интересы сервера, принимая запросы от клиентов и перенаправляя их на нужные бекенды.
🔹 Как работает:
* Клиент отправляет запрос на reverse proxy.
* Прокси решает, на какой сервер его перенаправить (например, по балансировке нагрузки).
* Сервер обрабатывает запрос и возвращает ответ через прокси.
Плюсы:
✅ Балансировка нагрузки – распределяет запросы между серверами.
✅ Кэширование – ускоряет отдачу статического контента.
✅ Защита бекендов – скрывает реальные серверы, фильтрует атаки (DDoS, SQL-инъекции).
✅ SSL/TLS Termination – разгружает бекенды, обрабатывая шифрование на себе.
✅ Маршрутизация – может перенаправлять запросы в зависимости от URL (API, статика, микросервисы).
Минусы:
❌ Единая точка отказа (нужна отказоустойчивость).
❌ Дополнительная задержка (если прокси перегружен).
Примеры использования:
* Веб-серверы (Nginx, Apache как reverse proxy для бекенда).
* CDN (раздача контента с ближайших серверов).
* API Gateway в микросервисных архитектурах.
Кэширование (для чего)
- Сокращение response time сервисов (главное)
- Снижение лишней нагрузки на сторонние сервисы
- Переиспользование ранее полученных или вычисленных данных
- Стабилизация работы при кратковременных отказах систем
По хорошему, нужно уметь держать нагрузку без кэша.
Задача кэша – ускорить ответ, а не держать нагрузку.
Термины кэширования
- Cache miss - промах кэша, запрошенный ключ не был найден в кэше
- Cache Hit - попадание в кэш, запрошенный ключ найден в кэше
- Hit ratio - процент попаданий запросов в кэш, характеризует
эффективность кэширования - Горячий ключ - ключ, на который приходится большая часть запросов
- Прогрев кэша - процесс наполнения кэша данными
Инвалидация- удаление кэшированных данных
Какие данные кэшировать
- Меняются часто (секунды) – кэшировать чаще всего бессмысленно, но иногда может пригодиться
- Меняются нечасто (минуты и часы) – чаще всего здесь задаемся вопросом – «стоит ли мне кэшировать»
- Меняются редко (дни, недели, месяцы) – в данном случае можно спокойно кэшировать эти данные
Кеширование ошибок
Кэшируем ошибки и тогда последующие запросы не
будут обращаться к источнику информации, а также не
будет cache miss attack
Как понять эффективен ли кэш
AverageTime = DBAccessTime * CacheMissRate + CacheAccessTime
Пусть:
- DBAccessTime = 100ms
- CacheAccessTime = 20ms
Тогда при CacheMissRate > 0.8 – кэш вреден!
Виды кэширования
- Внутреннее кэширование
Плюсы:
+ Высокая скорость
+ Отсутствие сетевых запросов
+ Нет расходов на Marshaling/Unmarshalling данных
Минусы:
- Горизонтальное масштабирование
- Прогрев кэша после падения сервиса - Внешнее кэширование
Плюсы:
+ Хранение большого объема данных
+ Простое горизонтальное масштабирование
+ После падения сервиса данные кэша не теряются
+ Простой прогрев кэша и простая логика инвалидации
Минусы:
- Скорость работы
Способы взаимодействия с кэшем
- Cache Aside (Кэширование на стороне) - приложение координирует запросы в кэш и БД и само решает, куда и в какой момент нужно обращаться
- Read Aside
- Write Aside
- Cache Through (Сквозное кэширование) - все запросы от приложения проходят через кэш
- Read Through
- Write Through
- Cache Ahead (Опережающее кэширование) - запросы на чтение всегда идут только в кэш, никогда не попадая в БД напрямую
Алгоритмы вытеснения данных
- Random
- FIFO (First In First Out)
- LIFO (Last In First Out)
- LRU (Least Frequently Used)
- MRU (Most Recently Used)
- MFU (Most Frequently Used)
Другие:
* Алгоритм Белади (OPT) - теоретический (если мы знаем когда будет обращение к элементу)
* Second Chance (FIFO с выставленным битом used)
* Clock (Тот же Second Chance, только не нужно двигать элемент из начала в конец очереди, если бит равен единице)
* 2Q
* SLRU (к данным добавляется их время жизни в кэше (TTL), по которому они автоматически удаляются из кэша)
* LRU-k
API
- REST (для клиентского взаимодействия)
- SOAP (уже умер)
- RPC (gRPC) (для внутреннего взаимодействия)
- GraphQL (для кастомизации запросов)