Что такое system design
System design — не зубрёжка известных архитектур, а дисциплина рассуждения от требований к узким местам и к компромиссам в условиях масштаба и отказов. Правильный ответ редко один — есть только защитимые. Этому кодинг уже не учит.
Двух инженеров просят «сделать сокращатель ссылок». Первый открывает редактор и пишет маршрут: хеширует длинный URL, сохраняет пару в таблицу и редиректит по выборке. На ноутбуке работает за двадцать минут. Второй спрашивает: сколько записей в секунду, сколько чтений, насколько коротким должен быть код, что будет, если два запроса дадут одинаковый хеш, что будет, когда база упадёт в три ночи? Первый написал код. Второй занимался system design — и только его версия переживёт контакт с миллионом пользователей. Зазор между этими двумя ответами — и есть весь предмет этого трека. К концу урока ты поймёшь, откуда этот зазор берётся и как начать его закрывать.
Это не зубрёжка
Когда садишься на интервью по system design — или пишешь реальный дизайн-документ — самая дорогая ошибка: считать это упражнением на запоминание. Распространённое заблуждение: system design — это запомнить, как устроены Twitter или Netflix, и пересказать диаграмму. Это противоположность навыка. Реальные архитектуры — ответы на конкретные ограничения: определённое соотношение чтений и записей, определённый бюджет задержки, определённая команда и бюджет; копируя ответ без вопроса, получаешь карго-культовый дизайн, который не подходит никому. System design — не свод фактов для заучивания; это способ рассуждать, применимый к задаче, которой ты раньше не видел.
Рассуждение идёт в одну сторону, и порядок важен:
- Требования — что система обязана делать и насколько хорошо? (функциональные и нефункциональные)
- Узкие места — при этих требованиях и заявленном масштабе какой ресурс сдаст первым?
- Компромиссы — чем платишь (консистентность, простота, стоимость, задержка), чтобы снять это узкое место?
Пропустишь шаг 1 — оптимизируешь не то. Пропустишь шаг 2 — масштабируешь часть, которая и не собиралась ломаться. Шаг 3 — где видна сеньорность: бесплатных побед почти не бывает, есть лишь выбранная цена.
Кодинг против проектирования
Кодинг спрашивает: «выдаёт ли эта функция правильный результат?» — вопрос с бинарным ответом, который проверяется юнит-тестом. Проектирование спрашивает: «выдержит ли эта система нагрузку, которой не видела, отказы, которые ты не предскажешь, и рост, который не остановишь?» — вопрос, на который ни один тест не вернёт зелёный. Функция либо корректна, либо нет. Дизайн же всегда лишь защитим или нет: он явно проговаривает свои допущения, называет нагрузку, на которую рассчитан, и говорит, чем и почему жертвует.
Поэтому «у меня на ноутбуке работает» — это начало разговора, а не конец. У ноутбука один пользователь, нет конкурентности, нет сетевого разделения, нет диска, что заполняется в полночь. Проектирование — это практика рассуждать обо всём, что ноутбук от тебя спрятал. Поймаешь себя на мысли «тесты зелёные — готово»: спроси себя — готово при каком масштабе, при каком отказе, для каких пользователей?
▸Почему это работает
Почему «правильный ответ редко один»? Потому что каждый значимый выбор проектирования меняет одно желательное свойство на другое, и какой обмен правилен — зависит целиком от выданных тебе требований, а не от технологии. Сильная консистентность или низкая задержка? Больше денормализации (быстрые чтения, болезненные записи) или строгая нормализация (чистые записи, медленнее чтения)? Монолит (просто, один деплой, один домен отказа) или сервисы (независимое масштабирование, налог распределённых систем)? Ни у чего из этого нет универсально правильной стороны. Сеньорный ход — не «знать ответ», а вытащить компромисс вслух, привязать его к заявленному требованию и выбрать сторону, которой это требование требует. Junior говорит «возьмём Postgres». Сеньор говорит «Postgres, потому что нужны транзакции, и наши 5k записей/с влезают в один primary — если записи вырастут в 10×, вернёмся к шардированию».
Конкретный мини-пример
Возьмём сокращатель. Интервью по требованиям выявляет: 100 чтений на 1 запись, редиректы должны ощущаться мгновенно (p99 — 99-й перцентиль задержки — ниже 50 мс), коды короткие, и сбой редиректа куда хуже сбоя создания. Теперь дизайн пишется сам из требований, а не из туториала:
- 100:1 с перевесом чтений → поставь кэш перед чтениями; рабочий набор горячих ссылок живёт в памяти.
- «мгновенный редирект» → путь чтения должен избегать медленной выборки; предвычисляй и кэшируй, не вычисляй на горячем пути.
- «короткие коды» → не хешируй (коллизии, длина); выдавай счётчик и кодируй его в base-62.
- «сбой редиректа — худшее» → сделай путь чтения самым реплицируемым, самым кэшируемым, наименее хрупким компонентом, а путь записи пусть деградирует первым.
Суть не в том, что это тот самый дизайн сокращателя. Суть в том, что другой набор требований — скажем, ингест аналитики с перевесом записей или коды, которые нельзя угадать, — переворачивает половину этих решений. Поток остался тем же; ответ изменился, потому что изменились требования. Это и есть system design.
Что покрывает этот трек
Это трек основ: несущие концепции, которые ты переиспользуешь в любом дизайне, независимо от конкретного продукта. Ранние юниты строят словарь и физику — масштабируемость (задержка, пропускная способность, оси масштабирования, числа, которые должен знать каждый инженер), затем распределение данных, кэширование, консистентность, коммуникация, надёжность и остальное. Поздний юнит (юнит 09) берёт расплывчатое рассуждение выше и закаляет его в явную, повторяемую рамку проектирования — чек-лист, по которому ты идёшь под давлением. Отдельный трек кейсов затем тратит этот словарь на полные сквозные дизайны (сокращатель, лента, ограничитель частоты, чат), где ты видишь, как основы складываются в реальные архитектуры.
Интервьюер просит спроектировать сервис обмена фото. Какой первый ход — это ход system design, а не ход кодинга?
Почему в system design «правильный ответ редко один, есть лишь защитимые»?
Кодинг спрашивает, возвращает ли функция правильный результат — бинарный, проверяемый вопрос. Проектирование спрашивает, выдержит ли система нагрузку и отказы, которых не видела, поэтому дизайн никогда не просто «корректен»; он может быть лишь _______ — он называет свои допущения, заявляет масштаб, на который рассчитан, и обосновывает, чем жертвует.
- 01Каков трёхшаговый поток рассуждения в system design, и почему важен порядок?
- 02Чем проектирование отличается от кодинга?
- 03Почему в system design правильный ответ редко один?
System design — не зубрёжка: не запоминание того, как устроен Twitter, а способ рассуждать, применимый к задачам, которых ты не видел. Он идёт в фиксированном порядке: требования → узкие места → компромиссы под давлением масштаба и отказов. Кодинг задаёт бинарный, проверяемый вопрос «корректна ли функция?»; проектирование — «выдержит ли система?», на который ни один прогон не вернёт зелёный, поэтому дизайн всегда лишь защитим: явный о своих допущениях, целевой нагрузке и принятой цене. Поскольку каждый реальный выбор меняет одно хорошее свойство на другое, правильный ответ редко один — версия одного продукта с перевесом чтений и с перевесом записей хотят разных дизайнов. Этот трек основ строит переиспользуемые концепции (масштабируемость, распределение данных, кэширование, консистентность, коммуникация, надёжность); юнит 09 закаляет расплывчатое рассуждение отсюда в явную, повторяемую рамку; а отдельный трек кейсов тратит этот словарь на полные сквозные дизайны. Теперь, когда услышишь «нам нужен Kafka» — или поймаешь эту мысль у себя — ты распознаешь ход кодинга: выбор технологии до требований, в обход рассуждения, которое делает выбор защитимым.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.