---
title: Конспект источника 1 — К. Кардаманов «Как проходят архитектурные секции собеседования в Яндексе» (habr 564132)
source: https://habr.com/ru/company/yandex/blog/564132/
author: Костя Кардаманов, отдел технологий разработки Яндекса
конспект: подготовлено 2026-09-17, TASK-45.5; это первоисточник формата секции — каркас для methodology.md (TASK-45.2) и эталонного разбора classic-designs.md §1 (TASK-45.3)
статус: официальный текст Яндекса о формате; числа и решения — дословно из статьи
---

# Источник 1: статья Яндекса о практике дизайна распределённых систем (habr 564132)

Единственный официальный первоисточник формата нашей секции: автор проводит такие интервью сам. Всё, что в `methodology.md` названо «6 этапов», и весь эталонный разбор URL shortener в `classic-designs.md` §1 выросли отсюда. Конспект — выжимка статьи с расчётами; читать до тренировок по §1 URL shortener.

---

## 1. Формат секции: что сказал интервьюер

- Секция по дизайну систем назначается **кандидатам уровня senior+** (кодовая секция — всем). Проверяется не «минимум» (код), а **достаточность** навыков: способность разработать сложную систему целиком.
- Задание — **спроектировать сложную, высоконагруженную и отказоустойчивую систему**; за основу берут реально существующую (пример статьи — Яндекс Go).
- **Кандидат — основной участник беседы**, интервьюер играет второстепенную роль и перехватывает инициативу только в крайних случаях. Молчать и ждать вопросов — проигрышный сценарий.
- План беседы и критерии оценки «достаточно просты» — автор прямо советует **запомнить план и придерживаться его** в процессе.

## 2. План секции: 5 основных блоков + дополнительные вопросы

| # | Этап (формулировка статьи) | Что делать |
|---|----------------------------|------------|
| 1 | **Уточнение задачи**: формализация требований, оценка аудитории, порядок нагрузки | Вытянуть числа вопросами; выделить функциональные и ключевые нефункциональные требования (время ответа, доступность, согласованность); **записывать требования**, чтобы не потерять к концу беседы |
| 2 | **Потоки данных, API, основные блоки** | Что входит и что выходит; из этого — программный интерфейс и состав основных сервисов. Выписать сущности и сигнатуры базовых API-методов |
| 3 | **Детальная схема**: компоненты и их роли, устройство самой важной части, структура БД | Концептуальная модель данных; найти самые нагруженные компоненты; алгоритмы/псевдокод для самого сложного места. **Сбалансированность сложности**: готовое решение вместо самописного |
| 4 | **Оценка вычислительных ресурсов, поиск узких мест** | CPU/память/диск/сеть на компонент; latency numbers вспомнить обязательно. Не хватает вертикали — менять алгоритм/структуру данных или горизонтально масштабироваться (второе «обычно выигрышнее в долгосрочной перспективе», цена — сложность и эксплуатация) |
| 5 | **Топология и эксплуатация**: балансировка, отказы, мониторинг, обслуживание, экстремальные условия | ДЦ/CDN/кэширование; переживание отказа сервера и ДЦ; **план на критическую ошибку в проде и на превышение нагрузки в разы/порядки** (чем жертвуем для выживания); обновления и смены схемы данных; в конце — **вернуться к требованиям из этапа 1** и показать, как контролировать их метриками |
| + | **Дополнительные вопросы** (если осталось время) | Устройство фреймворков/БД/алгоритмов; качество сервиса глазами пользователя; тестовые контуры, rolling releases, CD; версионирование данных; отладка в работающем кластере |

Соответствие методичке: этапы 1–5 = §1 `methodology.md` (тайминг 8/7/5/18/7/10 мин); блок «доп. вопросы» в 60-минутном слоте обычно не достигается — это буфер.

## 3. Что оценивается (критерии, разбросанные по тексту)

Отдельного чек-листа в статье нет, но интервьюер называет измерения, по которым судит о senior-кандидате:

1. **Формализация требований** и оценка аудитории/нагрузки до любой схемы.
2. **Гипотезы при нехватке данных**: «выдвигать обоснованные гипотезы можно и нужно» — на основе известного (население планеты, доля интернета). Ступор от отсутствия цифр — минус.
3. **Знание классов хранилищ и их свойств**: «нам важнее свойства и предоставляемые системой гарантии, чем конкретное название» (пример: Memcached для персистентных данных — ошибка; Redis на терабайты редкоменяемых данных — сомнение). Знать класс KVS и его представителей (Aerospike, Redis, Couchbase, Memcached, HBase), чтобы «делать разумный выбор».
4. **Минимальная сложность и стоимость** (KISS): «система должна быть минимально сложной и дешёвой в разработке и эксплуатации»; готовое решение вместо собственной разработки, «не усложняйте без лишней необходимости».
5. **Оценка ресурсов и узких мест**: расчёты от характеристик железа и latency numbers; понимание «бутылочного горлышка».
6. **Сценарии отказов и меры предотвращения** — прямая ответственность разработчика; эксплуатация/HA как область знаний (SRE).
7. **Метрики**: подход **metrics first** — «сначала определить или построить метрику, которую улучшаете, и только затем менять систему»; метрики — и работоспособность в моменте, и основа ретроспективного анализа планов.
8. **Видение системы в 4 измерениях**: компоненты и связи сейчас + выдерживаемая нагрузка сейчас + развитие на годы вперёд (замена компонентов, рост данных, будущее горлышко) + причины отказа.
9. **Ясно и аргументированно выражать мнение** — решения обсуждаются командой; одиночных архитекторов уровня крупных систем не бывает.

## 4. Эталонная задача: URL shortener (500k RPS, 1 млрд ссылок)

Условие: высоконагруженная система сокращения URL для компании масштаба Facebook, бесплатная и платная версии; платная не ограничивает RPS/число ссылок/TTL и даёт более короткие ссылки.

### 4.1 Этап 1 — диалог с числами (учить наизусть)

| Вопрос кандидата | Ответ |
|---|---|
| Объём переходов по ссылкам? | **500 тыс. RPS в пике** |
| HTTP или HTTPS? | Оба, преимущественно HTTPS |
| Сколько ссылок в базе? | **1 млрд всего**, у платных — 1 млн |
| Сколько аккаунтов? | Сотни тысяч бесплатных, тысячи платных |
| Скорость ответа? | **150 мс для 95 % запросов на чтение** |
| Доступность? | **Четыре девятки на чтение** |
| Согласованность? | **Новые ссылки — строго согласованы; модификация существующих — допускается чтение неактуальных несколько секунд** |
| Лимит бесплатного аккаунта? | 1000 запросов/мин |
| Новые ссылки? | Сотни тысяч в день |
| Анонимные ссылки? | В базовой версии — не реализуем; в расширенной — «можно подумать» (ограничения на добросовестное использование) |

Производные: ≈10–20 RPS записи против 500k RPS чтения → дизайн про чтение; «строго для новых» + eventual для правок → двухуровневое хранение с путём согласованности для новых ссылок.

### 4.2 Этап 2 — блоки и API

- **Control plane** — управление аккаунтом и ссылками: авторизация, управление аккаунтом, статистика по ссылкам, поиск/модификация/удаление. REST — сразу и для веб-UI, и для сторонних систем. Нагрузка — единицы RPS, «на дизайн системы в целом не повлияет».
- **Data plane** — переход по ссылке: `GET /{id}` → HTTP 302.
- **Кодирование идентификаторов**: генерация **random** (исключить перебор). 1 млрд ≈ 2^30 → 32 бита; base36 (36 символов): 36^6 ≈ 2.2 млрд → **6 символов**, «+1 разряд для исключения перебора» → **7**. Платные: 1 млн ≈ 2^20 → 36^4 ≈ 1.7 млн → **4+1 = 5 символов**.

### 4.3 Этап 3 — детали, БД, синхронизация

**Хранение (источник правды)**: любая реляционная СУБД, две таблицы:

- `Account(account_id, login, type)` — сотни тысяч записей, десятки байт/запись → **единицы МБ**.
- `Link(link_id, account_id, ttl, created, accessed, url)` — 1 млрд записей, сотни байт/запись → **сотни ГБ**.

Запись ~10–20 RPS (хватит одного сервера), чтение заведомо выше одного сервера. Managed-СУБД, объём **без шардирования**, схема **primary + hot standby**; между равнозначными веб-серверами — транзакции против race condition.

**Синхронизация с KV**: при любом изменении `Link` — репликация в KV store; альтернатива — собственная репликация через таблицу журнализации `Oplog(id, link_id, account_id, optime, url)`; «применение журнала и отставание реплик — тема доп. вопросов».

**Вместо 2PC — majority-коммит**: двухуровневое хранение повышает сложность → проблема «записалось в одно, не записалось в другое». 2PC дорог → **коммитить в СУБД после подтверждения записи от большинства реплик KV**; мусор в KV от непрошедших коммитов чистит **фоновая сборка мусора**.

**Read-контур (data plane)**: несколько HTTP-серверов + собственный модуль выдачи и rate-limit; балансировка DNS или **L3 IPVS round robin + health checks**. Алгоритм обработки запроса:

1. По ID из KV store (read-only зеркало: `link_id → {url, account_id}`) получить URL и владельца.
2. Проверить лимит аккаунта **по read-only-таблице `account_id → RPS` в разделяемой памяти**, которую раз в секунду обновляет отдельный процесс (сотни тысяч ключей × 4–6 байт, сортированный список, единицы МБ). Превышение → HTTP 429.
3. Регистрация обращения — **асинхронно**: счётчики аккаунтов (`account_id → counter`) копятся в памяти воркера и раз в секунду уходят в RPS limiter; ID затронутых ссылок копятся в set и **раз в минуту** уходят в очередь.

**KV store**: пары `link_id → {url, account_id}`, **~100 тыс. RPS на сервер**, данные ~**сотни ГБ** (100 байт/ссылка), CPU почти не тратится → **не шардировать, а реплицировать**. Чтение с secondary, которые отстают → путь согласованности новых ссылок: **L1 LRU-кэш на веб-сервере** — промаха мимо KV (L2) → поход в центральную СУБД → ответ кэшируется в L1 (ограничивает нагрузку на СУБД).

**LAT actuator** (актуализация времени доступа): сервисный процесс забирает из очереди (multiple producers, single consumer — реализована на том же KV) накопленные множества, сливает и делает `UPDATE Link SET accessed = now() WHERE link_id IN (...)`. Отказоустойчивость: несколько равнозначных процессов, на каждой итерации захват служебной записи `SELECT ... FOR UPDATE`.

**RPS limiter**: выбор «отдельный gRPC-сервис vs состояние в основной СУБД» — по принципу **минимизации расходов при приемлемом качестве и рисках**. Выбрано: состояние в центральной базе + асинхронная актуализация. Плюсы: нет отдельного сервиса с репликацией/консенсусом; состояние персистентно и согласовано. Минусы и их адресация: задержка актуализации (единицы секунд — приемлемо); риск отказа data plane при перевыборах primary → воркеры работают по снимку из разделяемой памяти; риск перегрузки СУБД → **никакой прямой записи из data plane в СУБД, всё через распределённую очередь**. Механика:

- `RPSLimit(account_id, balance, limit)` — тысячи записей (окно квотирования короткое, нулевые записи исключаются) → снимок ~полмегабайта.
- Лучше: `RPSLimitSnapshot(data BYTEA)` — полный снимок, сериализованный в бинарный формат (protobuf) со сжатием → **на порядок меньше данных**, можно чаще; воркеры забирают полное состояние раз в ~100 мс.
- Алгоритм — **leaky bucket**: события вычитают ёмкость корзины, раз в квант корзина доливается; полная корзина (balance = limit) — запись удаляется из состояния. Бонус — **burst budget** (кратковременное превышение лимита).

**Фоновые процессы**: поиск и удаление ссылок с истёкшим TTL, сборка мусора от незавершённых транзакций; запуск по таймеру с захватом блокировки.

### 4.4 Этап 4 — оценка ресурсов (считаем от дефицитного ресурса)

- **Data plane**: дефицитный ресурс — CPU: **HTTPS дороже plain HTTP на порядок** (handshake, несмотря на session reuse и аппаратные инструкции) → **~20 тыс. RPS на воркер**. KV store (100k RPS) CPU не тратит → ставить **инстанс KV рядом с каждым веб-сервером**: память сервера утилизируется, сетевая подсистема разгружается, надёжность выше. Итого **25 воркеров** на 500k RPS.
- **Отказоустойчивость**: консенсуса в контуре нет, число регионов не важно; сервис должен переживать отказ целого региона и сохранять 25 работоспособных воркеров → **9 серверов × 4 ДЦ** (запас на обновление/отказ до двух воркеров при недоступном регионе) + **4 IPVS** (по числу ДЦ — не удлинять маршрут за пределы ДЦ) + **3 сервера СУБД** (консенсус для автопереключения primary). **Итого 43 сервера**.
- **Время ответа**: пинг NY–Москва ~120 мс → на ответ сервера остаётся ~30 мс из 150. Воркер: KV на localhost — единицы мс + сервер — единицы мс + маршрутизация в ДЦ — сотни мкс → **≤10 мс, большой запас** → географическое распределение дополнительно не нужно.
- Control plane: единицы CPU, несколько локаций; СУБД — доминирует диск (~десяток CPU), полноценный сервер.

### 4.5 Этап 5 — топология и эксплуатация

Балансировка на всех уровнях — round robin, нагрузка равномерная.

**Сценарии отказов** (проговаривать по каждому компоненту):

| Отказ | Эффект и реакция |
|---|---|
| IPVS-балансировщик | Нагрузка на оставшиеся 3, многократный запас |
| Веб-сервер / KV store | Размазывается по 8 соседям в ДЦ; при пиковой нагрузке держим 6 воркеров в ДЦ — иначе исключаем ДЦ из балансировки |
| Secondary СУБД | Не влияет |
| Primary СУБД | Влияет на control plane, не влияет на GET |
| RPS limiter и вспомогательные | Основные функции работают, риски растут |

**Защита от превышения нагрузки на чтение**: короткие пики — запасом по времени ответа (очередь на воркерах); детект подозрительного трафика на IPVS (хосты/подсети, blacklist от воркеров); blacklist за одинаковые/несуществующие ссылки; понижение криптостойкости SSL.

**Мониторинг**: агрегация по классам серверов (primary/secondary СУБД, KV, веб-сервер, IPVS, RPS limiter, вспомогательные); ресурсы (CPU/RAM/disk IO/net IO) по серверам и процессам; количество и время обработки запросов **по квантилям**; коды ответов с защитой от шума (частые несуществующие ссылки, аккаунты с исчерпанной квотой).

**Логи и трассировка**: логи веб-серверов при таких объёмах дороги и сами влияют на производительность → писать на SSD/NVMe, часто ротировать, сжимать, перекладывать в дешёвое хранилище (первый уровень — HDD на том же сервере); уровни избыточности по возрасту архива; отладочная трассировка — каждый k-й запрос и/или по флагу в запросе.

**Обновление**: воркеры независимы, теряем до 3 в ДЦ без потери качества → катим **по 3 воркера, ДЦ строго последовательно**, сравнивая метрики с остальными. Тестовый контур меньшего размера с репликой, куда дублируется каждый k-й продовый запрос. СУБД — обновление с коротким даунтаймом после проверки на тестовом контуре (чтение не страдает).

**Доп. вопросы** (если осталось время): устройство выбранных фреймворков/БД/алгоритмов; качество сервиса с точки зрения пользователя; локализация/персонализация; тестовые контуры, rolling releases, CD; версионирование данных; быстрые срезы данных под экстремальную нагрузку; поиск проблем и отладка в работающем кластере.

## 5. Принципы статьи (звучат как критерии оценки)

1. **KISS / минимальная сложность**: система минимально сложна и дешёва в разработке и эксплуатации; готовое вместо самописного; «не усложняйте без лишней необходимости».
2. **Metrics first**: сначала метрика, которую улучшаем, потом изменение системы; метрики — инструмент и моментального контроля, и ретроспективы.
3. **Гипотезы при нехватке данных**: обоснованная гипотеза вместо ступора; данные вытягиваем вопросами, требования записываем.
4. **Гарантии важнее названий**: выбирать по свойствам и гарантиям хранилища, а не по бренду; знать представителей каждого класса.
5. **Разделение control plane / data plane**: управление (единицы RPS, REST, любая СУБД) отдельно от горячего пути чтения (500k RPS, 302, никаких тяжёлых синхронных зависимостей); общий пул балансировщиков — отказ data plane не валит control plane.
6. **Majority-коммит вместо 2PC** при двухуровневом хранении + фоновая GC для мусора; согласованность «строго для новых» — отдельным путём (L1-кэш мимо отстающих реплик).
7. **Асинхронная актуализация всего, что вне критического пути**: accessed (очередь + батч-UPDATE), счётчики RPS (память воркера → очередь → лимитер), лимиты воркером — из снимка в разделяемой памяти. Общий рефрен: «такой способ увеличит критический путь».
8. **Сценарии отказов и мониторинг**: по каждому компоненту — что будет при отказе и как это видно; квантили, шумоподавление; план на ошибку в проде и на экстремальную нагрузку (чем жертвуем).
9. **Ресурсы от дефицитного ресурса**: TLS→CPU→20k RPS/воркер; ко-локация компонентов по взаимодополняющим ресурсам (CPU веб-сервера + память KV на одной ноде); запас — сценариями (9×4), не «лишними серверами».
10. **Видение в 4 измерениях**: сейчас + нагрузка + развитие на годы + причины отказов; горизонтальное масштабирование «выигрышнее в долгосрочной перспективе».
11. **Инженерная коммуникация**: ясно, чётко, аргументированно; умение объяснить решение — часть работы senior/архитектора.

## 6. Рекомендации статьи по подготовке

- Освежить литературу и доклады о дизайне реальных систем: Таненбаум «Распределённые системы», Бёрнс «Паттерны проектирования распределённых систем», **Kleppmann DDIA**, Google SRE; доклады HighLoad++.
- The System Design Primer — «отличная методичка», но без теоретической базы легко запутаться (в нашем плане — источники 2–3).
- Практика: взять сложную систему (хранилище, видеохостинг, поиск, лента, мессенджер, обработка заказов) и **прогнать по плану на доске/листе**; ideally — с слушателем-разработчиком. Совпадает с нашим протоколом тренировок `methodology.md` §6.
- Курсы System Design Interview автор не рекомендует (платные, качество решений низкое).

## 7. Пересечения с эталонными разборами (classic-designs.md, TASK-45.3) и методичкой

Конспект — первоисточник; в производных документах он уже разложен так:

| Материал статьи | Где живёт в наших материалах |
|---|---|
| 6-блочный план секции + рекомендация «запомнить и придерживаться» | `methodology.md` §1 (этапы с таймингом) и §2 (фреймворк ответа по этапам) |
| Диалог-вытягивание требований (таблица чисел §4.1) | `classic-designs.md` §1 «Этап 1. Требования» — дословно та же таблица вопросов и ответов |
| Разбор URL shortener целиком (блоки, БД, majority-коммит, RPS limiter, LAT actuator, ресурсы 25/9×4/43, эксплуатация) | `classic-designs.md` §1 «URL shortener — эталон Яндекса» — полный конспект решения по 6 этапам |
| Принципы §5 этого конспекта | `classic-designs.md` §1 «Чему учит эталон» (6 паттернов) и `methodology.md` §3 (речевые паттерны: гипотеза, трейдофф, гарантии вместо брендов, KISS, критический путь, metrics first, чекпоинты) |
| Типовые ошибки (молчание, усложнение, синхронный критический путь…) | `methodology.md` §4 «Топ-10 ошибок» — выведены из антипримеров статьи |
| Список литературы статьи (DDIA, SRE, Primer) | `methodology.md` §5 порядок чтения и `knowledge-base.md` §12 (карта DDIA) |

Практический вывод: **URL shortener из этой статьи — вероятный формат и эталон нашей секции** (HR дал её первой в списке материалов). Тренировочный приоритет: URL shortener → лента новостей (заявленный фокус секции «инстаграм/твиттер») → мессенджер → медиа-хостинг.

## Связанные документы

- [`../methodology.md`](../methodology.md) — фреймворк секции, построенный на этой статье (§1–4)
- [`../classic-designs.md`](../classic-designs.md) — эталонный разбор URL shortener (§1) и остальные билеты
- [`../knowledge-base.md`](../knowledge-base.md) — числа и паттерны (latency numbers упомянуты в статье как обязательные)
- [`../README.md`](../README.md) — индекс папки и план чтения
