Job 2026 md

title: Статья 10 — Прикладные компоненты и паттерны source: подготовлено 2026-09-17, TASK-45.50; каркас — brief.md §10; развёртка — knowledge-base.md §13–14; источники — Alex Xu Vol. 1 гл. 4, 7, 9, 13 (TASK-45.38), learn-system-design Ultimate Guide (TASK-45.24); отсылки — статьи 01, 04, 07, 08, 09, 11, 12 серии, classic-designs.md


Статья 10: прикладные компоненты и паттерны

Раздел-арсенал: готовые блоки, из которых собираются ответы на типовые вопросы этапов 2 и 4. Всё остальное в серии — про то, как вести секцию (01), считать (02), выбирать хранилища и механизмы (04–09); здесь — шесть именованных компонентов, которые интервьюер может спросить отдельно или которые нужны в билете: дизайн API, rate limiter, генераторы ID, real-time доставка, поисковый краулер, автозаполнение. Критерий «умею, если» из брифа жёсткий и формульный: для любого из компонентов могу в 2 фразах описать схему и трейдофф.

Формула раздела, которая экономит минуты секции: «две фразы: схема + трейдофф». Первая фраза — как устроен механизм (по стрелке данных); вторая — чем за это платим и что получаем взамен. Не лекция, не «могу рассказать подробнее», а именно две фразы — и готовность развернуть любую в детали по запросу. Проверка на себе перед секцией: если про компонент сначала вспомнилось название технологии, а не стрелка данных и цена — компонент не готов.

Место раздела в секции: на этапе 2 (потоки и API) мы фиксируем контракт — и обязаны знать, каким он бывает (REST/gRPC, пагинация, идемпотентность, 429 в контракте ошибок); на этапе 4 (детали) компоненты встраиваются в схему: rate limiter на входе, snowflake для ID сущностей, WebSocket-шлюзы в мессенджере, trie в поиске. На этапе 6 (эксплуатация) у каждого компонента своя метрика: доля 429, число WS-коннектов, лаг пересборки typeahead. Глубина — ../knowledge-base.md §13–14; полные конспекты глав Сюя — ../materials/alex-xu-vol1/ch-04-rate-limiter.md, ch-07-unique-id-generator.md, ch-09-web-crawler.md, ch-13-typeahead.md; в эталонах компоненты уже встроены — ../classic-designs.md.

1. Дизайн API: контракт, который не стыдно показать

Схема в двух фразах. REST поверх HTTP — ресурсный контракт (существительные + глаголы HTTP, кэшируемость и коды статусов из коробки) для публичных API и всего, что ходит через стандартную инфраструктуру; gRPC — бинарный protobuf поверх HTTP/2 со строгими типами и стримингом — для внутренних вызовов сервис–сервис, где важны латентность и контракт. Пагинация коллекций — курсором (opaque-токен «продолжай после этой позиции»), идемпотентность записей — idempotency key, который клиент генерирует и который сервер дедуплицирует.

Трейдоффы, которые надо называть:

  • REST vs gRPC: REST — читаемость, отладка curl'ом, HTTP-кэширование, но многословный JSON и никакой схемы (OpenAPI — договорённость, не контракт); gRPC — компактность, генерация клиентов, двунаправленный стриминг, но сложнее браузерам (нужен grpc-web), тяжелее отладка и LB (HTTP/2, long-lived коннекты → least connections, KB §13.2). Правильная формула: «наружу REST, между сервисами gRPC — если есть причины, иначе и внутри REST».
  • Offset vs курсорная пагинация: offset/limit прост и умеет «страница №N», но при вставках страницы дрейфуют (элемент уезжает между страницами), а глубокий offset — O(offset) в БД. Курсор стабилен и O(1) — «дай после post_id=X, 20 штук», но нельзя прыгнуть на произвольную страницу и нужен стабильный порядок сортировки. Для лент и любых «бесконечных» списков — курсор; для админки с пагинацией по номеру — offset допустим.
  • Идемпотентность записей: повтор запроса ≠ двойной эффект. Idempotency key (UUID клиента) в заголовке, сервер хранит «ключ → ответ» и на повтор отдаёт тот же результат. Это то же самое «at-least-once + дедуп», что в очередях (статья 07 §5), только на HTTP-границе — и это то, что делает безопасными ретраи клиента и доставку событий.
  • Коды ошибок — часть контракта: 4xx — вина клиента и повторять бессмысленно без исправления (кроме 429 — «отступи и повтори по Retry-After»), 5xx — наша вина, ретраить можно (идемпотентно). 429 и Retry-After проектируются заранее (§2), а не появляются как 500 «internal error» на перегрузке.

Уровень детализации на этапе 2: 3–5 сигнатур, не код — метод, путь, ключевые поля запроса/ответа; control plane (создать/удалить, единицы RPS) отделён от data plane (горячий путь чтения) (статья 01 §3).

2. Rate limiter: считаем и отсекаем на входе

Схема в двух фразах. По ключу (user_id / IP / API key) считаем запросы в скользящем или фиксированном окне/корзине и всё сверх лимита отсекаем кодом 429 с заголовком Retry-After, не тратя ресурсы системы. Стоит он рано — на API-шлюзе/входе в сервис — и решает две задачи: защита от абьюза и защита системы от себя (каскадная перегрузка, статья 08 §7).

Алгоритмы — таблица, которую надо уметь проговорить (KB §14.1, Сюй гл. 4):

Алгоритм Идея Плюсы Минусы
Token bucket В корзину капают токены со скоростью R; запрос берёт токен; нет токена — отказ Допускает burst (копятся токены), гибкие два параметра (ёмкость, скорость) Burst надо осознанно ограничить ёмкостью
Leaky bucket (бриф акцентирует) Запросы встают в очередь, из неё вытекают с постоянной скоростью Ровный выходной поток — идеально для защиты слабого бэкенда Burst режется целиком; по сути те же два параметра
Fixed window counter Счётчик на окно (минута) Просто, дёшево по памяти Burst ×2 на границе окон: 100 в конце окна + 100 в начале следующего
Sliding window log Храним таймстампы каждого запроса Точно Дорого по памяти при большом RPS
Sliding window counter Взвешиваем предыдущее окно + текущее Компромисс цены и точности Оценка, не точный лимит

Разница token/leaky в одном: token bucket допускает всплески (и это фича для API), leaky bucket выравнивает поток (и это фича для защиты бэкенда с жёстким потолком). На секции безопасная формулировка: «на входе token bucket как контракт для клиента, перед тяжелым бэкендом — leaky bucket как стабилизатор».

Трейдоффы, которые надо называть: точность против памяти — sliding log точен, но хранит каждый запрос; fixed window дёшев, но пропускает burst ×2 на границе окон; точность против распределённости — локальный счётчик мгновенен, но врёт за балансировщиком; общий лимит через Redis — честный, но добавляет ход в горячем пути (и eventual между ДЦ).

Распределённый limiter: счётчики не в памяти воркера, а в Redis, инкремент и проверка лимита — одной Lua-операцией (атомарный check-and-set, иначе гонка между воркерами: каждый насчитал «ещё можно» — пропустили вдвое больше). Мульти-ДЦ: лимитер живёт на edge (GeoDNS ведёт в ближайший узел), между узлами лимит — eventual: суммарный лимит может на секунду превышаться на величину лага — учесть в нагрузочных тестах. Клиентские лимитеры (в SDK) — экономия вызовов; источник правды — серверный.

Эксплуатация: в ответе 429 + Retry-After (и/или X-RateLimit-Remaining/-Limit) — честный клиент отступает сам; мониторим долю заблокированных — высокая доля означает либо абьюз, либо неверно выбранный лимит, оба случая — actionable. Противоядие от «забыли лимитер» на этапе 6: вопрос «что защищает систему от удвоения трафика?» имеет ответ «rate limiter на шлюзе + load shedding в глубине (08 §7)».

3. Генераторы ID: уникальность без координации

Схема в двух фразах. Snowflake — 64 бита: 41 бит — таймстамп в мс (~69 лет), 10 бит — номер ноды (1024 ноды), 12 бит — последовательность (4096 ID/мс на ноду); каждая нода генерирует ID сама, без похода в центр — уникальность дают разложенные биты (время + уникальный номер ноды), а время в старших битах даёт «бесплатную» сортировку по возрастанию. Альтернативы по лестнице простоты: UUID v4 (128 случайных бит, вообще без координации), auto-increment одной БД (строгий порядок, но одна точка), централизованный ticket service с выдачей диапазонов нодам (кэшируем блоки ID — генератор не на критическом пути записи).

Трейдоффы, которые надо называть:

  • UUID v4: нулевая координация, но 128 бит раздувает индексы, случайность ломает локальность B-tree и не даёт порядка — нельзя сортировать «по ID» и шардировать по времени. Хорош для correlation-id и записей без порядка, плох для первичных ключей больших таблиц.
  • Auto-increment: порядок есть, но генератор — единая точка (и узкое место записи); трюк «чёт/нечет на две ноды» масштабируется плохо и предсказуем (утечка объёмов).
  • Snowflake: 4096 ID/мс × 1024 ноды ≈ 4 млрд ID/с — запас на любой билет; цена — зависимость от часов: часы нод расходятся (NTP), при откате времени возможны дубли → откат отрабатываем ожиданием/буфером, а «порядок по ID» — приблизительный (часы разных нод не идентичны, миллисекунды разных нод могут пересекаться — развязка по номеру ноды). И главное — связь со статьёй 09: snowflake обходит консенсус — уникальность без единого источника, но и без строгого глобального порядка; если бизнесу нужен строгий порядок (номер документа, короткая ссылка) — нужен централизованный источник.
  • Короткая ссылка ≠ snowflake: 64 бита — это ~11 символов base62 минимум; для URL shortener нужен короткий ключ — base62 от последовательности или случайный 7-символьный с проверкой уникальности (эталон — ../classic-designs.md §1). Snowflake хорош для ID сущностей (посты, сообщения, заказы), где длина не критична.

Формула для секции: «ID сущностей в масштабе — snowflake: без координации, сортировка по времени бесплатно, платим зависимостью от NTP и приблизительностью порядка».

4. Real-time доставка: транспорт по направленности

Схема в двух фразах (по каждому варианту). Короткий polling — клиент сам опрашивает раз в N секунд: тупо и надёжно, но холостые запросы и задержка до N. Long polling — сервер держит HTTP-запрос открытым, пока не появится событие, клиент тут же переоткрывает: реальное время поверх обычного HTTP, работает через старые прокси. SSE — открытый HTTP-поток «сервер → клиент» с автопереподключением из коробки: односторонний, но самый дешёвый в реализации. WebSocket — после HTTP-upgrade дуплексный TCP-канал: оба направления, один коннект, минимальный overhead на сообщение.

Выбор — таблица KB §13.3, критерий один: направленность + совместимость инфраструктуры:

Задача Транспорт Почему
Мессенджер, коллаб-редактор, live-обновления WebSocket Дуплекс: и входящие, и «прочитано/печатает»; LB — least connections/sticky, ping/pong keepalive
Нотификации, обновления ленты, цены SSE Только сервер → клиент; поверх HTTP, авто-reconnect — в 5 раз проще WS
Старые клиенты/корпоративные прокси Long polling WS не проходит — имитируем push обычными запросами
Простые статусы («готово/не готово») Short polling Цена холостых запросов известна и мала
Push наружу (интеграции) Webhook Сервер → сервер, HTTP POST на зарегистрированный URL
Звонки/видео WebRTC → HLS/CDN P2P-медиа; ingest → RTMP, раздача → HLS/DASH + CDN

Трейдофф, вокруг которого крутится раздел: WebSocket — эффективность ценой stateful-инфраструктуры. Коннект живёт на конкретном шлюзе → шлюз stateful: реплицировать нечего, но routing сообщений между шлюзами нужен (пользователь подключён к шлюзу A, отправитель — к шлюзу B: сводим через pub/sub в Redis или очередь — так устроен мессенджер, ../classic-designs.md §3); LB — least connections, не round robin; keepalive ping/pong, иначе LB и NAT рвут «тихие» коннекты; отказ шлюза = обрыв всех его коннектов → клиенты переподключаются (reconnect storm — выдерживаем джиттером и backoff, 08 §5), недоставленное — из офлайн-очереди при переподключении. SSE и long polling — stateless-ish по коннектам и потому дёшевы в эксплуатации.

Формула для секции: «транспорт выбираю по направленности: дуплекс — WebSocket, только сервер→клиент — SSE, зоопарк клиентов — long polling; WebSocket означает stateful-шлюзы, и у меня для них есть routing и reconnect-история».

5. Поисковый краулер: обход графа с вежливостью

Схема в двух фразах. Обход ориентированного графа страниц: seed URL → frontier (очередь «что качать») → загрузчик (с DNS-кэшем — резолв 10–200 мс, без кэша это узкое место) → дедуп контента по хешу (~29 % страниц — дубликаты; «видели ли URL?» — фильтр Блума) → извлечение ссылок → фильтр → обратно в frontier. Цикл живёт, пока не исчерпан бюджет; состояние (frontier, «виденное») — в хранилище, чтобы пережить падение воркера.

Вторая фраза раскрывается в главную идею — frontier не FIFO, а две группы очередей (Сюй гл. 9): лицевые (front queues) — приоритет по ценности страницы (PageRank, популярность, частота обновления): BFS «в лоб» качает мусор и бьёт веером по ссылкам одной страницы в один домен; тыльные (back queues) — вежливость: хеш по домену → своя FIFO на домен → выделенный воркер с гарантированной паузой между запросами к одному серверу. Плюс robots.txt: кэшируем и уважаем Disallow — иначе «краулер, который DDoS'ит чужие сайты», это провал на секции и в проде.

Числа для калибровки (KB §14.2): 1 млрд страниц/мес ≈ 400 QPS среднее (пик 800), при 500 КБ/страница — 500 ТБ/мес, ~30 ПБ за 5 лет → хранение и дедуп — не мелочь, а половина дизайна.

Трейдоффы: приоритизация (качаем ценное первым) против полноты обхода; фильтр Блума — память в разы меньше, но ложные срабатывания (редкие URL сочтём виденными — приемлемо для краулера, фатально для биллинга); один глобальный frontier — просто, но далеко от источников; гео-распределённый краулинг — быстрее и вежливее локально, дороже в консистентности «виденного». Спайдертрапы (календарь-бесконечность): лимит длины URL и глубины, чёрные списки; таймауты на медленные серверы; server-side рендеринг JS-страниц — отдельная дорога (headless-браузер), назвать как расширение.

6. Автозаполнение (typeahead): префиксное дерево с готовыми ответами

Схема в двух фразах. Ядро — trie (префиксное дерево) с частотами, и главная оптимизация: в каждом узле храним готовый топ-k популярных дописываний — ответ на запрос это спуск по префиксу (по буквам, O(длины)) + чтение готового списка, без обхода поддерева и сортировки на лету. Топ-списки строятся офлайн: логи запросов → агрегаторы частот (для Google — неделя, для Twitter — реальное время) → воркеры пересобирают trie → снапшот в БД/KV → сервисы грузят trie в память → API отвечает из памяти.

Числа для калибровки (KB §14.4, Сюй гл. 13): 10M DAU × 10 запросов × 20 символов ≈ 24k QPS (пик 48k) — запрос на каждый введённый символ; требование отклика <100 мс, топ-5 подсказок. Наивный алгоритм (обход поддерева + сортировка на каждый запрос) на таком QPS не живёт — поэтому топ-k в узлах.

Трейдоффы: предвычисленный топ-k в каждом узле — платим памятью (каждый узел хранит список), забираем латентность (O(1) на выдаче); свежесть подсказок — офлайн-пересборка даёт лаг минут/часов (для трендов — инкрементальные обновления или подмешивание realtime-списка поверх снапшота); шардирование trie — по диапазонам префиксов (a–f → нода 1), горячие префиксы — репликами; ограничение максимальной длины префикса — вторая оптимизация памяти. Вариант вопроса «топ-k самых частых запросов за период» — это тот же дизайн: агрегатор частот + топ-k структуры (heap/Count-Min), переиспользуем схему.

7. Сводная таблица: компонент → две фразы → трейдофф

Ядро раздела — критерий брифа. Таблица — шаблон «двух фраз» для репетиции: закрыть таблицу и проговорить каждую строку вслух за 60 секунд на компонент.

Компонент Фраза 1: схема Фраза 2: трейдофф Где звучит
API (REST/gRPC) REST наружу (ресурсы, HTTP-семантика, курсорная пагинация, idempotency key), gRPC между сервисами (protobuf, HTTP/2) REST — читаемость и HTTP-кэш ценой многословности; gRPC — скорость и строгий контракт ценой отладки и LB для HTTP/2 Этап 2 любого билета (01 §3)
Rate limiter По ключу считаем запросы в окне/корзине (token/leaky bucket), сверх лимита — 429 + Retry-After; распределённо — Redis + Lua на входе шлюза Точность против памяти (sliding log точен и дорог; window counter дёшев и врёт на границе ×2); на edge — eventual между ДЦ 08 §7 (перегрузка), шлюз в любой схеме
ID (snowflake) 64 бита: 41 время + 10 нода + 12 секвенция — каждая нода генерирует сама, старшие биты дают сортировку по времени Без координации и без единой точки, но порядок приблизительный (часы нод) и нужна дисциплина NTP; UUID — нулевая координация, но раздутые индексы и нет порядка 09 §7 (уникальность), 11 §3–4 (посты, сообщения)
Real-time транспорт Дуплекс — WebSocket (upgrade, один коннект), однонаправленно — SSE поверх HTTP, совместимость — long polling; routing между WS-шлюзами через pub/sub WS — эффективность ценой stateful-шлюзов (sticky/least-conn LB, reconnect storm, офлайн-очередь); SSE — дёшев, но только сервер→клиент 11 §3 (мессенджер), 11 §2 (лента)
Краулер Графовый обход: frontier (front-очереди по ценности + back-очереди по доменам с паузами) → загрузчик с DNS-кэшем → дедуп по хешу/Блуму → извлечённые ссылки в frontier Приоритет против полноты; Блум — память против ложных срабатываний; вежливость (паузы, robots.txt) обязательна — иначе DDoS источников Отдельный вопрос; общий паттерн «очередь задач + воркеры» (07)
Typeahead Trie с частотами, в каждом узле — готовый топ-k; топ-списки пересобираются офлайн из логов, снапшоты раздаются сервисам Память (топ-k в каждом узле) против латентности (O(1) выдача); свежесть — лаг офлайн-пересборки Поиск в ленте/маркете; «топ-k запросов»

8. Ошибки этого раздела

Ошибка Как выглядит Противоядие
Название вместо схемы «Возьмём Redis» / «будет WebSocket» — без стрелки данных и цены Формула «2 фразы: схема + трейдофф»; сначала механизм, потом технология (§7)
Rate limiter «в каждом сервисе» Лимитируют на 5 ярусах, клиент получает 429 непонятно от кого Один источник правды на шлюзе; вложенные лимитеры — только с осознанной иерархией (§2)
Fixed window по умолчанию «Счётчик на минуту» — а burst ×2 на границе окон проходит Назвать границу окон вслух; sliding window counter как компромисс (§2)
Забыли контракт отказа 429 без Retry-After; клиент долбится ретраями 429 + Retry-After + X-RateLimit-* — часть API-контракта (§1, §2)
Snowflake «просто генератор» Не названы биты, NTP и приблизительность порядка 41+10+12, откат часов — буфером, строгий порядок — централизованный источник (§3)
Короткая ссылка из snowflake 64-битный ID → 11+ символов ключа — «короткая» ссылка не короткая Ключ — base62 последовательности/случайный с проверкой уникальности (§3, classic-designs §1)
WebSocket везде Push-нотификации через WS, а это SSE за час работы Выбор по направленности (§4); WS — только дуплекс
WS без истории эксплуатации Не сказано про stateful-шлюзы, LB и обрывы коннектов Routing через pub/sub, least connections, ping/pong, reconnect с джиттером (§4)
Краулер-BFS в лоб FIFO по ссылкам → штурм одного домена и мусор в приоритете Front/back очереди, пауза на домен, robots.txt (§5)
Typeahead на лету Обход поддерева и сортировка на каждый запрос при 48k QPS Топ-k в узлах, офлайн-пересборка, память против латентности (§6)
Offset-пагинация в ленте offset 100000 — дрейф страниц и O(offset) в БД Курсор для бесконечных списков, offset — только для «страница №N» (§1)

9. Что назвать на секции (чек-лист раздела)

Обязательные фразы и действия. Полный чек-лист — ../methodology.md §7; канон — ../knowledge-base.md §13–14.

На этапе 1 (требования): вытащить из вводной, какие компоненты нужны: «real-time?» → транспорт; «абуз/публичный API?» → rate limiter; «поиск/подсказки?» → typeahead. Не рисовать компонент, которого нет в требованиях, — но знать, что он появится, если интервьюер спросит.

На этапе 2 (API): контракт из 3–5 сигнатур с идемпотентностью записей (idempotency key) и курсорной пагинацией для списков; в контракте ошибок — 429 + Retry-After; control plane отделён от data plane (01 §3).

На этапе 3–4 (схема и детали): - Rate limiter — на входе, до дорогих операций: «token bucket на шлюзе, Redis + Lua, ключ — user_id; высокие 429 мониторим» (§2). - ID сущностей — snowflake одной фразой: «64 бита: время + нода + секвенция, без координации, сортировка по времени бесплатно» (§3). - Real-time — транспорт по направленности + одна фраза про stateful-шлюзы: «WS-шлюзы stateful, routing через pub/sub, reconnect с backoff» (§4). - Краулер/typeahead по запросу — front/back очереди и топ-k в узлах, каждый со своим числом-калибровкой (§5–6).

На этапе 6 (эксплуатация): у каждого компонента своя метрика: доля заблокированных (rate limiter), число живых коннектов и reconnect-шторма (WS), лаг пересборки топ-списков (typeahead), глубина frontier (краулер) — «метрика привязана к узлу, а не списком в конце» (KB §13.8; глубина — 12-operations-observability.md).

Сквозные формулы раздела:

  • «Любой компонент — две фразы: схема по стрелке данных + чем плачу; детали — по запросу».
  • «Лимитирую на входе, отвечаю 429 + Retry-After, мониторю долю отказов».
  • «Snowflake: уникальность без координации, время в старших битах; строгий порядок — отдельно».
  • «Транспорт — по направленности: дуплекс WS, сервер→клиент SSE, совместимость long polling».
  • «Краулер — это вежливость: очереди на домен, паузы, robots.txt».

10. Самопроверка «умею, если»

Критерий раздела из брифа: для любого из компонентов могу в 2 фразах описать схему и трейдофф. Протокол проверки (закрытые материалы, вслух, 60 секунд на компонент): для каждого из шести — фраза-схема, фраза-трейдофф, затем «где этот компонент встал бы в билете инстаграм/твиттер» (rate limiter — шлюз, snowflake — ID постов, WS — мессенджер, typeahead — поиск). Затем четыре зонда: (1) «чем leaky bucket отличается от token bucket?» (ровный выход vs допустимый burst), (2) «почему для ленты не offset-пагинация?» (дрейф и O(offset) — курсор), (3) «как масштабируете WS-шлюзы?» (stateful: least-conn LB, pub/sub routing, reconnect backoff), (4) «как краулер не DDoS'ит сайты?» (back-очереди на домен + пауза + robots.txt). Маркеры готовности: (1) шесть строк таблицы §7 проговариваются без запинки и без подглядывания; (2) у каждого компонента всплывает число-калибровка (4 млрд ID/с, 48k QPS typeahead, 400 QPS краулер); (3) на «а что если упадёт…» у WS-шлюза и лимитера есть готовая история с метрикой. Протокол тренировок и рубрика 0–3 — ../methodology.md §6; встроенные примеры — ../classic-designs.md §1–4. Если «две фразы» звучат раньше названия технологии — раздел готов.

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

  • 00-overview.md — обзорная статья по всем 12 разделам брифа (TASK-45.40); §10 — карта раздела
  • 01-interview-framework.md — этап 2: сигнатуры API, control vs data plane, идемпотентность в контракте
  • 02-estimations.md — числа-калибровки компонентов (QPS, storage)
  • 04-data-models-storage.md — где живут данные компонентов (KV для лимитера, снапшоты trie, хранилище frontier)
  • 07-queues-streams.md — rate limiter как защита входа в очередь; frontier краулера как очередь задач; идемпотентность at-least-once
  • 08-fault-tolerance.md — rate limiting/load shedding в картине перегрузки; backoff + jitter для reconnect
  • 09-consistency.md — snowflake обходит консенсус; уникальность без порядка vs со строгим порядком
  • 11-reference-designs.md — эталоны, где компоненты встроены: snowflake и rate limiter в shortener/ленте, WebSocket в мессенджере
  • 12-operations-observability.md — метрики компонентов на этапе 6 (доля 429, коннекты, лаг пересборки)

  • ../brief.md — бриф: раздел 10 с критерием «умею, если»

  • ../knowledge-base.md — §13 (инфографика: LB-алгоритмы 13.2, транспорт 13.3, ID 13.4, локи 13.5) и §14 (rate limiting 14.1, краулер 14.2, уведомления 14.3, typeahead 14.4)
  • ../methodology.md — §4 топ-10 ошибок, §6 протокол тренировок, §7 карточка на секцию
  • ../classic-designs.md — §1 shortener (генерация короткого ключа), §3 мессенджер (WS-шлюзы и routing)
  • ../materials/alex-xu-vol1/ch-04-rate-limiter.md — источник: алгоритмы rate limiting, распределённый limiter, заголовки 429 (TASK-45.38)
  • ../materials/alex-xu-vol1/ch-07-unique-id-generator.md — источник: разбор snowflake по битам, ticket service, хеш по порядку (TASK-45.38)
  • ../materials/alex-xu-vol1/ch-09-web-crawler.md — источник: frontier, вежливость, фильтр Блума, числа краулинга (TASK-45.38)
  • ../materials/alex-xu-vol1/ch-13-typeahead.md — источник: trie, топ-k в узлах, офлайн-конвейер, шардирование по префиксам (TASK-45.38)
  • ../materials/lsd-ultimate-guide-image.md — расшифровка инфографики: real-time транспорт, API-шлюз, генерация ID (TASK-45.24)
  • Соседние статьи: 09-consistency.md (уникальность и порядок ID — отсылки в §7 таблице) · 11-reference-designs.md (компоненты встроены в эталоны) · 12-operations-observability.md (метрики компонентов)