Job 2026 md

title: Конспект материала 26 — awesome-scalability (binhnguyennus) source: https://github.com/binhnguyennus/awesome-scalability author: Binh Nguyen — курируемая подборка «patterns of scalable, reliable and performant large-scale systems» конспект: подготовлено 2026-09-18, TASK-45.30; README прочитан целиком (~700 ссылок, 11 разделов); топ-5 отобраны и прочитаны полностью — 3 инженерные статьи (Instagram, Netflix, Twitter/High Scalability) + 2 статьи из PDF (Brewer IEEE 2001, TAO USENIX ATC'13) статус: P3-источник «после секций», но топ-5 — это готовые боевые кейсы ровно под наш бриф «инстаграм/твиттер + отказоустойчивость»: три кейса закрывают компоненты крупноблочной схемы (хранилище+ID, соцграф, кэш лент), два — операционный и понятийный слои деградации. Учебников и шпаргалок в репо нет — только кейсы и первоисточники


Материал 26: awesome-scalability — индекс и топ-5

awesome-scalability — крупнейшая из просмотренных подборок (~700 ссылок), но устроена иначе, чем учебники: это каталог реальных кейсов компаний, разложенный по проблемам («система тормозит» / «система падает» / «готовишься к интервью»). Знаний «с нуля» здесь нет — роль учебников у нас остаются SDP, karanpratapsingh и DDIA. Ценность другая: почти к каждому пункту нашей крупноблочной схемы (хранилище, ID, соцграф, кэш, деградация) есть battle-tested ответ конкретной компании с числами — это слой «а как это устроено в проде», которым отвечают на уточняющие вопросы интервьюера.

1. Как устроен источник

Раздел Что внутри Доля Ценность для нас
Principle Фундаментальные статьи: Brewer «Giant-Scale Services», Jeff Dean (Google), 12-factor, CAP/ACID/BASE, consistent hashing, «Life Beyond Distributed Transactions», anti-patterns ~60 ссылок Ядро — понятийный слой деградации и масштабирования
Scalability Кейсы по подсистемам: кэш (FB/Etsy/Netflix), Redis, очереди/Kafka, хранилища (MySQL/Postgres/Cassandra/TAO), шардирование (Instagram, Pinterest, Uber), поиск ~420 ссылок Ядро — кейсы под компоненты схемы
Availability / Stability HA и устойчивость: failover, rate limiting, autoscaling, circuit breaker'ы, таймауты, bulkheads (Netflix, Stripe, Cloudflare, GitHub) ~90 ссылок Ядро — вторая половина брифа («отказоустойчивость»)
Performance Оптимизация: латентность, GC, кэш CDN, профилирование (Dropbox cross-shard 10M RPS, Netflix, Instagram) ~70 ссылок Второй эшелон — точечные цифры
Architecture Целые архитектуры компаний с диаграммами: Medium, Shopify, Pinterest feed, LinkedIn, Monzo, Slack ~55 ссылок Референсы «как выглядит ответ целиком»
Interview Заметки про формат: lethain «Architecting Systems for Scale», «How NOT to design Netflix», Jeff Dean talk ~25 ссылок Формат у нас уже закрыт (Поломодов, моки)
Intelligence / Organization / Talk / Book ML-инфра, орг-масштабирование, доклады, книги ~180 ссылок Вне брифа

2. Критерии отбора топ-5

  1. Прямая релевантность брифу: крупноблочная схема сервиса класса Instagram/Twitter + отказоустойчивость; каждый пункт закрывает конкретный компонент схемы или блок «деградация».
  2. Не дублировать уже покрытое: кэш-кейс Facebook/Memcached уже есть (материал 12), Redis-топологии и шардирование-теория — материал 15, fan-out ленты — classic-designs.md §2. Поэтому из кэша берём флот Twitter (а не ещё один FB), из шардирования — ID-генерацию Instagram (а не очередную таксономию).
  3. Доступность и читаемость: все топ-5 бесплатны и прочитаны целиком; выбирайте статьи, которые дают числа и конкретные решения, а не списки ссылок.

3. Топ-5

# Материал Компания / год Компонент схемы Бриф / KB
1 Sharding & IDs at Instagram Instagram, 2012 хранилище + генерация ID бриф 04–05 / KB §6, §13.4
2 TAO: Distributed Data Store for the Social Graph Facebook, USENIX ATC'13 соцграф (подписки) бриф 02, 09 / KB §7, §9
3 How Twitter Uses Redis to Scale — 105TB, 39MM QPS Twitter, 2014 кэш лент бриф 06 / KB §4, §9
4 Fault Tolerance in a High Volume Distributed System Netflix, 2012 деградация: таймауты, bulkhead, fallback бриф 08 / KB §9
5 Lessons from Giant-Scale Services Brewer / Inktomi, 2001 деградация: yield/harvest/DQ бриф 03, 08 / KB §9

3.1 Sharding & IDs at Instagram (2012) — шардирование + ID без координатора

Выжимка. Instagram 2012: «25 фото и 90 лайков в секунду», Django + PostgreSQL. Когда встало шардирование, от NoSQL отказались — шардировали сам Postgres. Требования к ID: сортируемость по времени (лента фото сортируется без дополнительных фетчей), 64 бита (компактные индексы и «лучше живёт в Redis»), минимум новых движущихся частей («мы масштабировались малой командой именно за счёт простых решений»). Разбор альтернатив: ID на стороне приложения (Mongo ObjectId — 12 байт, UUID — 96+ бит, часть UUID случайны и не сортируются); отдельный сервис-генератор (Twitter Snowflake: 64 бита, сортируемо, переживает смерть нод, но ZooKeeper + отдельный сервис — лишние движущиеся части); ticket-серверы на БД (Flickr: два сервера с чётными/нечётными — предсказуемо, но риск write-бутылочного горлышка, а при нескольких БД теряется сортируемость). Решение: тысячи logical-шардов, замапленных в коде на несколько физических — логический шард = Postgres schema; решардинг = перенос схем между машинами без перебакетинга данных (тот же приём, что hashslot'ы Redis Cluster и логические шарды TAO/ Pinterest). Шард выбирается по user_id (user_id % 2000). ID собирается в самой БД (PL/PGSQL-функция, DEFAULT next_id(), RETURNING на INSERT): 41 бит мс от кастомной эпохи (41 год) + 13 бит логического шарда + 10 бит автоинкремент mod 1024 (= 1024 ID на шард в мс); шард-идентификатор внутри ID даёт бесплатный маппинг «ID → шард».

Что брать на секцию. - Прямой ответ на «как генерируете ID» (KB §13.4): структура Snowflake (время + шард + последовательность) существует в двух вариантах — внешний сервис (Snowflake/ZooKeeper: больше движущихся частей, переживает отказ нод) и внутри БД (Instagram: ноль новых компонент, но 1024 ID/шард/мс и часы БД как источник времени). Уметь назвать оба и выбрать. - «Почему 64 бита, а не UUID»: индексы вдвое компактнее, ID сортируемы, 64 бита «удобно для Redis» — пример, как выбор ID определяется downstream-системой (кэш лент). - Решардинг без даунтайма: логических шардов сильно больше физических, двигаем логические юниты, а не данные. Один и тот же приём у Redis Cluster (слоты), Instagram (schemas), TAO (шарды > серверов) — три источника, одна формулировка. - Честный минус, если спросят: 10 бит последовательности = 1024 записи/мс/шард — при бёрсте на один шард этого может не хватить; время берётся с часов шарда (расхождение часов ≈ лёгкое нарушение сортируемости).

3.2 TAO — Distributed Data Store for the Social Graph (Facebook, USENIX ATC'13) — соцграф как компонент

Выжимка. Статья про хранилище соцграфа: миллиард чтений и миллионы записей в секунду, тысячи машин, много петабайт. Модель: типизированные ноды (64-битный id) + типизированные направленные рёбра (id1, atype, id2, time) — «подписки», «лайки», «авторство»; обратные рёбра ведутся автоматически. Мотивация: раньше веб-серверы читали граф из MySQL через look-aside memcache — много round-trip'ов и слабые гарантии; TAO заменяет это graph-aware кэшем (кэш понимает семантику: кэшированный счётчик «0» сам отвечает на range-запрос) поверх MySQL-шардов. Распределение нагрузки: 99.8% чтений / 0.2% записей; большинство запросов рёбер возвращают пустоту (assoc get находит ребро лишь в 19.6% случаев, 45% assoc count = 0); распределения с длинными хвостами (1% счётчиков ≥ 512K). Хранение: логических шардов больше, чем серверов; id объекта содержит id шарда, ребро живёт на шарде id1 — каждый запрос обслуживается одним сервером (локальность!). Кэш двухуровневый: leader + follower tiers — клиенты ходят в ближайший follower, все записи шардa идут через его leader (естественная сериализация + защита БД от thundering herd); запись с обратным ребром цепляет RPC к чужому шарду, атомарности нет — «висячие» рёбра чинит фоновая джоба. География: граф невозможно порезать по пользователям (слишком связный) — полная копия на регион; писать в master-регион, читать локально (read misses в 25 раз чаще записей — поэтому так). Консистентность: eventual, лаг репликации обычно < 1 с; read-after-write внутри одного tier через changeset + номера версий; для немногих запросов, где нужна строгость (пример из статьи — аутентификация), есть critical reads — проксируются в master-регион. Отказоустойчивость: агрессивные таймауты + простой failure detector (несколько подряд таймаутов → нода помечается down, запросы к ней прерываются превентивно); падение master-БД → автопромоушен слейва (записи во время свитча помечаются failed и не ретраятся); падение leader'а → чтения напрямую в БД, записи — случайному члену leader-tier + асинхронная починка консистентности; потерянные инвалидации компенсируются bulk invalidation по shard id после замены ноды; у клиента primary + backup follower tier. Хвосты: hot objects → shard cloning + client-side cache с версиями; арен в slab-аллокаторе на тип данных — изоляция «плохих соседей»; объекты с >6000 связей целиком не кэшируются.

Что брать на секцию. - Соцграф — отдельный компонент схемы «инстаграм/твиттер» (кто на кого подписан, что fan-out воркеры читают при доставке): read-mostly 99.8/0.2, длинные хвосты, собственный кэш-иерархия. Одна фраза уровня «в проде это TAO: leader-кэш поверх шардов MySQL, миллиард чтений в секунду» резко поднимает ответ. - Локальность ребра: ребро живёт на шарде id1 → любой запрос по одному ребру = один сервер. Тот же принцип relationship-based шардирования, что и в материале 15 §3.2, но от Facebook. - Пустые результаты — 80%+ запросов: кэшировать негативные ответы (кэшированный «0» отвечает за range-запрос) — неочевидная деталь, редко звучит на интервью. - «А если нужна строгость?» — critical reads к master (аутентификация/деньги) при eventual-по-умолчанию: готовый ответ, как в AP-системе точечно получают CP-поведение. Стыкуется с KB §7. - Отказоустойчивость (бриф 08): при отказах TAO маршрутизирует вокруг упавших, жертвуя свежестью, а консистентность чинит позже (bulk invalidation) — живая иллюстрация выбора AP из CAP и фразы «мы продолжаем рендерить Facebook, даже если данные устарели».

3.3 How Twitter Uses Redis to Scale — 105TB RAM, 39MM QPS, 10,000+ Instances (2014) — кэш лент в проде

Выжимка. Масштаб: суммарно 105TB RAM и 39M QPS на >10 000 инстансов; один Timeline-кластер одного ДЦ — ~40TB и ~30M QPS на >6000 инстансов. Timeline — самый важный сервис Twitter: Home Timeline — просто список tweet id (до ~3000 записей), User Timeline — ещё один такой же список. Почему Redis, а не Memcached: (1) network bandwidth problem — записи инкрементальные и маленькие, чтения маленькими батчами, а объект большой; read-modify-write целой ленты на каждый твит — сетевое бутылочное горлышко (на гигабите при 100K+ оп/с и среднем объекте >1KB сеть упирается первой); Redis — «data structure server»: инкрементальные операции выполняются на сервере над структурой; (2) long common prefix problem — иерархические ключи и упаковка (ziplist) экономят память на повторяющихся префиксах. Форкнули Redis 2.4: добавили Hybrid List (список ziplist'ов с порогом в байтах: предсказуемая память и латентность записи; чистый ziplist давал «write latency trap» — большая лента селебрити при расширении вытесняла кучу мелких ziplist'ов и всплескивала латентность) и BTree (range-запросы по иерархическим ключам). Цена специализации — застряли на форке 2.4. Кластер: сравнили три варианта (серверы сами договариваются / proxy / клиентская логика) и выбрали proxy: «разделить fast path (данные) и slow path (управление)», сервер остаётся «simple, dumb, fast», а изменения клиентов раскатывались бы годами по ~100 проектам; прокси stateless, масштабируются добавлением. «Лишний хоп — миф»: через прокси <0.5ms, а типичный путь между Java-сервисами (Finagle) ~10ms — «проблема внутри JVM, а не в хопах». Redis-операции не идемпотентны: сетевой глитч + ретрай = тихо испорченные данные (список с выпавшим куском выглядит нормальным), поэтому — централизованный cluster leader: look-aside кэш, при падении ноды шард переезжает, вернувшаяся машина флашится. Операционка: логируют каждую команду при 100K QPS (C-кэш, только метаданные), сырые логи — 10MB/с на бокс «экономически не увезти» → предагрегация на боксе, сводки собирает Storm. Уроки: scale demands predictability; tail latencies matter (fan-out на много шардов: один медленный шард тормозит весь запрос); детерминированная конфигурация; JVM медленный, C быстрый (прокси вернули на C/C++).

Что брать на секцию. - Готовый ответ «почему для лент Redis, а не Memcached»: не «он быстрый», а инкрементальные операции над структурой на сервере (push/trim ленты) вместо read-modify-write больших объектов; память экономим упаковкой. Прямо стыкуется с нашей схемой ленты (classic-designs §2, кэш лент до ~3000 записей — то же число, что у Twitter). - Конкретика для блока кэша: ~3000 записей на ленту — «продуктовое решение, зашитое в низкоуровневый компонент» — хороший пример трейдоффа; Hybrid List — пример «добавь тип данных под workload, но получи форк». - Tail latency при fan-out — дословно наш KB §9 (tail amplification): «один медленный шард — медленный весь запрос» — теперь с цифрами 30M QPS. - «Хоп дешёвый (<0.5ms), JVM дорогой (~10ms)» — контринтуитивный аргумент, которым можно ответить на «не дорогой ли лишний прокси-слой». - Неидемпотентность кэш-операций + флаш упавшей ноды — деталь, которой почти ни у кого нет; хорошо звучит в ответе «что будет, если кэш-нода упала посреди записи».

3.4 Fault Tolerance in a High Volume Distributed System (Netflix, 2012) — операционная деградация

Выжимка. Netflix API: >1 млрд входящих вызовов в день, fan-out 1:6 к десяткам подсистем, пики >100K запросов к зависимостям в секунду, тысячи EC2-инстансов. Арифметика композиции отказов: 30 зависимостей по 99.99% дают 99.7% = 2+ часа даунтайма в месяц — «перемежающиеся отказы гарантированы». Худший тип отказа — латентность: одна зависимость, «зависшая» на высоком трафике, за секунды насыщает все request-треды Tomcat и роняет весь API. Набор защит: сетевые таймауты и ретраи; отдельные thread pool'ы на каждую зависимость; семафоры (tryAcquire, неблокирующие); circuit breaker'ы. Пул на зависимость: латентная зависимость насыщает только свой пул, Tomcat-треды освобождаются; бонус — зависимости дергаются параллельно (fan-out) и включается request collapsing (автобатчинг). Семафоры — для не-сетевых операций (in-memory cache lookup, где тред — лишний оверхед) и для защиты самих fallback'ов: fallback не должен звать сеть, но если кто-то так написал — семафор ограничит ущерб. Circuit breaker: порог (пример — 50% ошибок за 10 с) → rejection всех запросов до прохождения health checks: fail fast = shed load + быстрое восстановление. Ответ пользователю при отказе — лестница fallback'ов по мере ухудшения UX: (1) Cache — отдать из локального/удалённого кэша, пусть stale; (2) Eventual Consistency — записать в очередь (SQS), довести, когда зависимость вернётся; (3) Stubbed Data — дефолтные значения; (4) Empty Response («fail silent») — пустой список, который UI игнорирует; «fail fast» с исключением лучше накопления ожидающих. Слои таймаутов: thread timeout 300ms как общий бюджет; если зависимость легитимно бьёт 99.5-перцентиль (lazy generation при cache miss) — network timeout 325ms, 0–1 ретрай, thread timeout 350ms+; пул на 10 тредов держит всплеск p99, в здоровом режиме активны 1–2 треда при медиане 40ms. Конфигурации меняются в рантайме; система в проде 8 месяцев (реализация выросла в Hystrix).

Что брать на секцию. - Арифметика 30 × 99.99% = 2+ часа/мес — мгновенный ответ на «зачем таймауты, если каждая зависимость 99.99%». Одна формула — и видно, что отказоустойчивость нельзя «купить SLA зависимостей». - Bulkhead (пул на зависимость) + фраза «латентность хуже падения: падение видно сразу, латентность копится и роняет соседей через исчерпание тредов» — ядро брифа 08; связка с KB §9 (metastable failure через retry storm). - Лестница fallback'ов — готовый пункт «деградация функциональности»: кэш (stale) → очередь записи → дефолты → пустой ответ. Для ленты: «лента из кэша, счётчик лайков — заглушкой, лайк — в очередь». - Таймауты считаются от перцентиля зависимости, а не от среднего (300/325/350ms по p99.5) — конкретика, которая звучит как опыт; стыкуется с DDIA гл. 2 в KB §9. - Circuit breaker с параметрами «50% ошибок за 10 с» — вместо абстрактного «ставим предохранитель».

3.5 Lessons from Giant-Scale Services (Brewer, IEEE 2001) — словарь деградации: yield, harvest, DQ

Выжимка. Классика (Inktomi/ Berkeley), из которой выросла терминология «всегда доступных сервисов». Три метрики доступности: uptime, yield (completed queries / offered queries — доля обслуженных запросов) и harvest (data available / complete data — какая доля данных отражена в ответе); harvest распространяется и на фичи (у eBay может лежать «профиль продавца», пока остальное работает). Ключевой инсайт: можно управлять тем, куда бьёт отказ — в yield, harvest или оба. DQ principle: Data per query × Queries per second ≈ constant — ёмкость ограничена физическим бутылочным горлышком (движение данных: I/O, сеть); метрика измерима нагрузочным тестом, линейно масштабируется нодами (4-нодовый кластер Inktomi предсказывал эффект оптимизаций на 100-нодовом). Репликация vs партиционирование под отказом: реплики держат harvest, но роняют yield (load redirection: упало k из n — оставшиеся получают n/(n−k) перегруза; 2 из 5 → 166%); партиции держат yield, роняя harvest. «Репликация лучше» молчаливо предполагает свободную ёмкость — на высокой утилизации это неверно; настоящая цена репликации — DQ-очки на обслуживание копий, а не диск. Graceful degradation — явный процесс: пик/среднее 1.6:1–6:1 и коррелированные отказы делают насыщение неизбежным, поэтому заранее решаем, что резать: admission control (cost-based — отказать одному дорогому запросу, пропустив несколько дешёвых; priority-based — Datek гарантирует торговым заявкам 60 секунд или комиссию 0), reduced freshness (котировки обновляются реже → дешевле отдавать), dynamic database reduction (резать базу вдвое ≈ удвоить ёмкость). Плюс принцип MTTR важнее MTBF: новые фичи снижают MTBF и почти не двигают MTTR — фокус на быстром восстановлении и быстром цикле отладки.

Что брать на секцию. - Пара yield/harvest — самый короткий профессиональный ответ на «что отдаём при деградации»: «лента без рекомендаций и счётчиков = harvest порезан при полном yield; отказываем части запросов = yield». Одно слово «harvest» отличает осознанный ответ от «поставим кэш». - Расчёт перегруза выживших реплик n/(n−k) — ответ на «почему двух реплик мало при высокой утилизации»: отказ 1 из 2 удваивает нагрузку на выжившую. Репликация защищает данные, но не трафик без запаса ёмкости. - Таксономия деградации: admission control (по стоимости/приоритету), reduced freshness (для ленты — «допустим стейл до N минут»), database reduction — конкретные механизмы для блока «отказоустойчивость» вместо абстрактного load shedding (KB §9). - MTTR > MTBF — зрелая реплика для KB §10 (эксплуатация): «мы оптимизируем восстановление, а не предотвращение; поэтому канарейки, health checks и bulk invalidation». - DQ — формула на случай «когда хватит железа»: ёмкость = Data per query × QPS; уменьшаешь ответ (кэш, партиции) — растёшь в QPS при том же железе.

4. Второй эшелон (если секций будет больше одной)

Материал Что даёт Когда
Wix: Scaling to 100M — To Cache or Not to Cache рамка «кэшировать ли вообще» от компании на MySQL без NoSQL уточняющий вопрос про кэш
Building a Dynamic and Responsive Pinterest эволюция ленты Pinterest (Following Feed / Interest Feed) вторая лента-кейса
Manhattan, our Real-Time Multi-Tenant Distributed Database чем Twitter заменил Redis для персистентных данных вопрос «а где хранится правда»
Cross Shard Transactions at 10 Million RPS at Dropbox цена и механика кросс-шард транзакций на большой цифре бриф 09 / KB §7
The Calculus of Service Availability (Google) «доступность — свойство пользователя, не системы»: SLO × разные классы запросов разговор про SLO/SLA
How NOT to design Netflix in your 45-minute interview типовые ошибки формата перед секцией, 20 мин

5. Как использовать

  1. Кейсы (§3.1–3.3) — по одному компоненту схемы: ID+хранилище (Instagram), соцграф (TAO), кэш лент (Twitter). На каждый — 15–20 минут и одна фраза-маркер: «ID = время+шард+seq, считаем в БД, 1024/мс/шард»; «соцграф read-mostly 99.8%, ребро на шарде id1»; «лента — структура на сервере Redis, инкрементально, хвост решает».
  2. Деградация (§3.4–3.5) — два слоя одного ответа: понятия от Brewer (yield/harvest, n/(n−k), MTTR) + механизмы от Netflix (пулы, breaker 50%/10s, лестница fallback'ов, таймауты от перцентиля).
  3. Чего в репо нет: учебной теории и формата интервью — идти в ../methodology.md, ../classic-designs.md, lsd-polomodov-guide.md.

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

  • ../knowledge-base.md — §4 (кэш), §6 (шардирование), §7 (консистентность), §9 (отказоустойчивость), §10 (эксплуатация), §13.4 (генерация ID)
  • ../classic-designs.md — §2 (лента: fan-out; кейсы Twitter/TAO дают этому прод-подтверждение)
  • lsd-architecture-notes.md — материал 15: Redis-топологии и шардирование-теория (кейсы этого конспекта их иллюстрируют)
  • lsd-bytebytego-blog.md — материал 12: FB/Memcached (кэш-кейс-компаньон к Twitter/Redis)
  • learn-system-design-index.md — индекс подборки (этот материал — №26, Advanced, P3)