8-шаговое руководство для собеседования по Ace A System Design

Узнайте, как подходить к собеседованию по проектированию систем и получить работу в компании своей мечты.

Системное проектирование стало одним из важных этапов собеседования с разработчиками программного обеспечения, особенно на руководящую должность. Подготовка к этому раунду необходима для взлома интервью некоторых из самых популярных компаний, таких как Amazon, Netflix, Google, Twitter и т. Д.

Ожидается, что в этом раунде вы обсудите дизайн крупномасштабной распределенной системы, такой как Twitter, Uber, Facebook, Dropbox и т. Д.

Когда дело доходит до проектирования системы, не существует единственного правильного решения. Может быть несколько способов решить проблему, и поэтому этот раунд будет открытым, в котором основное внимание будет уделяться рабочему дизайну + вашему мыслительному процессу.

Почему так важно подготовиться к собеседованию по проектированию системы?

Из-за отсутствия опыта или знаний в построении масштабируемых систем в повседневной работе многие разработчики борются с этим раундом. Даже будучи хорошими разработчиками программного обеспечения, они не могут попасть в хорошие компании только потому, что не прошли этот раунд.

Поэтому важно сосредоточиться на этом раунде и хорошо подготовиться, чтобы попасть в компанию своей мечты.

Чего ожидать от собеседования по проектированию системы?

Великие инженеры тратят годы на создание надежной и масштабируемой системы. Вы не сможете придумать подобное решение за короткий промежуток в 1–1,5 часа на собеседовании по проектированию системы.

Так что, как правило, в этом раунде обсуждается только часть всей системы.

Как упоминалось ранее, не существует единственного правильного решения при разработке хорошей системы. Этот раунд, как правило, является открытым, и обсуждение может идти в любом направлении в зависимости от того, что интересует интервьюера, как вы ведете дискуссию и в каком направлении вы ее ведете.

Примеры вопросов, задаваемых на собеседовании по проектированию системы

  • Создайте чат, например WhatsApp
  • Дизайн парковки
  • Разработайте службу сокращения URL-адресов, например TinyURL
  • Разработайте сервис потокового видео, такой как YouTube / Netflix
  • Создайте сервис обмена файлами, такой как Google Диск
  • Создайте платформу социальных сетей, например Instagram, Twitter или Facebook.

Вот некоторые из популярных вопросов, которые задают в этом раунде. Как видите, вопросы расплывчаты, а в постановке проблемы не содержится конкретных деталей о том, какую часть системы следует разработать.

Итак, важно знать, как подойти к этому раунду, чтобы придумать хороший дизайн в конце этого обсуждения.

Различные раунды проектирования системы

Системное проектирование обычно делится на два отдельных этапа.

Но опять же, это зависит от компании и ее процесса. Так что будьте готовы разрабатывать в этом раунде компоненты системы как верхнего, так и нижнего уровня.

  • Дизайн высокого уровня
  • Низкоуровневый дизайн

Дизайн высокого уровня:

Этот раунд в основном проверяет вашу способность проектировать и разрабатывать высокоуровневые компоненты для заданных требований.

Например, для такой постановки задачи, как Разработайте платформу социальных сетей, например Instagram, вам нужно придумать различные микросервисы, которые вам понадобятся, механизм pub-sub (при необходимости), очереди, базы данных и т. Д. кеширование и др.

Интервьюер задаст вопросы о том, как данные будут передаваться через различные микросервисы в дизайне, отказоустойчивости, механизме повтора и т. Д. Вы также можете ожидать вопросов о нефункциональных требованиях, таких как масштабируемость, согласованность данных, параллелизм и т. Д.

Построить распределенную масштабируемую систему сложно. Придумывая архитектуру, вы должны думать о различных сценариях.

Различные концепции, которые вам следует изучить, чтобы подготовиться к раунду HLD:

  • Ключевые характеристики распределенных систем
  • Балансировка нагрузки
  • Кеширование
  • Разделение данных
  • Индексы
  • Прокси
  • Резервирование и репликация
  • SQL против NoSQL
  • Теорема CAP
  • Последовательное хеширование
  • Длинный опрос против WebSockets против событий, отправленных сервером

Низкоуровневый дизайн:

Этот раунд в основном фокусируется на вашей способности разрабатывать низкоуровневые компоненты вашего HLD. Учитывая постановку проблемы, вы должны разработать дизайн с различными сущностями, классами и атрибутами, наследованием, составом, шаблонами проектирования, базами данных, таблицами и схемами и т. Д.

Вы не можете охватить все это за один раунд собеседований. Интервьюер может заинтересовать кого угодно в зависимости от того, как идет обсуждение.

Различные концепции, которые вам следует изучить, чтобы подготовиться к раунду LLD:

  • UML
  • Диаграмма вариантов использования
  • Диаграмма классов
  • Дизайн базы данных
  • Схема последовательности
  • Диаграмма деятельности
  • Разделение проблем
  • Принципы ООП
  • ТВЕРДЫЕ принципы и т. Д.

Как подойти к раунду собеседований по системному дизайну?

Вот мое 8-шаговое руководство по эффективному подходу к этапам разработки системы.

Шаг 1. Задайте много вопросов и определите рамки собеседования:

Формулировки проблем системного дизайна расплывчаты. И нет единственного правильного ответа. Итак, важно задать много вопросов и уточнить рамки обсуждения.

Кандидаты, задающие много вопросов, имеют больше шансов на успех. Например, вот список вопросов, которые вы можете задать на вопрос Дизайн Instagram:

  • Какие типы аккаунтов возможны?
    О: Только пользователи. Мы пока не будем рассматривать бизнес-аккаунты
  • Какие типы сообщений может публиковать пользователь?
    О: Предположим, пользователи могут публиковать только изображения для этого обсуждения. Видео выходит за рамки.
  • Могут ли пользователи подписываться на других пользователей?
    О: Да
  • Должны ли мы поддерживать теги для каждого сообщения?
    О: Да
  • Могут ли сообщения быть личными?
    О: Предположим, что сообщения могут быть общедоступными только для этого обсуждения.
  • Могут ли пользователи искать сообщения?
    О: Да
  • Должны ли мы сосредоточиться на архитектуре на стороне клиента или на архитектуре на стороне сервера?
    О: Я хотел бы понять взаимодействие клиент-сервер на высоком уровне. Но больше внимания следует уделять созданию масштабируемой серверной системы.
  • Сколько пользователей, как ожидается, будут использовать систему каждый день?
    О: Предположим, что у нас около 100 миллионов пользователей, заходящих в систему каждый день.
  • Стоит ли нам сосредоточиться на создании домашнего фида пользователя?
    О: Давайте не будем зацикливаться на алгоритме генерации фида
  • Следует ли нам сосредоточиться на высокоуровневом или низкоуровневом дизайне системы?
    О: Давайте обсудим высокоуровневый дизайн системы в этом обсуждении

Вот некоторые из примеров вопросов, которые вы можете задать, чтобы задать рамки обсуждения. Как вы видите, теперь мы знаем, что нам нужно сосредоточиться на создании высокоуровневого дизайна Instagram. Нам не нужно учитывать, что пользователи публикуют видео. Нам не нужно думать о создании домашних лент пользователей разумным способом. так далее

Шаг 2: Определение интерфейса системы

После того, как мы окончательно определим требования, следующим шагом будет составление списка API-интерфейсов, которые нам понадобятся для построения системы.

Вы должны определить различные API-интерфейсы REST и их контракты для поддержки заданных требований.

Например, в нашем примере с Instagram нам понадобятся несколько примеров API:

storePhoto (user_id, tags, image_url, user_location,…)
getPhoto (image_id)
likePhoto (image_id, user_id)

Конечно, это примеры API. API, используемые в реальном приложении, намного сложнее.

Шаг 3. Оценка емкости и ограничения

В вашей системе должно быть достаточно памяти и ресурсов для обработки ожидаемой нагрузки и количества пользователей, которые могут использовать вашу систему через 1 год, через 5 лет и т. Д.

Поэтому важно оценить, сколько ресурсов вам нужно выделить при проектировании системы, чтобы избежать проблем в будущем.

Если у вас есть база данных в проекте вашей системы, кэш в вашей системе, процесс оценки емкости обычно включает вычисление того, сколько памяти используется на ежедневной основе для всех баз данных и кластеров кеша.

Это дает нам хорошую оценку того, сколько памяти нам понадобится через годы.

Оценка емкости также помогает в том, как мы проектируем нашу систему так, чтобы ее можно было масштабировать по горизонтали и вертикали для более высоких требований к емкости в будущем.

Вот расчет того, сколько хранилища необходимо для хранения фотографий в нашем примере Instagram:
Согласно нашему предположению, приведенному выше, у нас ежедневно регистрируется 100 миллионов пользователей.

Предположим, что 1 миллион пользователей загружают в среднем по 2 фотографии каждый день.

2 млн фотографий загружаются каждый день

Это означает, что каждую секунду добавляются 23 фотографии

Предположим, средний размер фотографии составляет 400 КБ.

Ежедневное пространство для хранения: 2 млн * 400 КБ = ›800 ГБ

Необходимое хранилище на 5 лет:
800 ГБ * 365 (дней в году) * 5 (лет) ~ = 1425 ТБ

Хранилище, необходимое на 10 лет:
800 ГБ * 365 (дней в году) * 10 (лет) ~ = 2850 ТБ

Шаг 4. Дизайн высокого уровня

На этом этапе это помогает перечислить все высокоуровневые компоненты, которые задействованы в системе, и то, как они взаимодействуют друг с другом.

Это могут быть микросервисы, базы данных, кеши, очереди сообщений, недорогие сервисы хранения и т. Д.

В нашем примере с Instagram мы можем создать два отдельных микросервиса. За загрузку фотографий отвечает одна служба. Еще один сервис для получения фотографий.

Какой смысл в двух отдельных микросервисах, спросите вы?

Причина этого в том, что запросы на загрузку фотографий обычно ниже, чем запросы на чтение фотографий. Таким образом, мы можем масштабировать услуги отдельно в зависимости от требований трафика.

Мы даже можем использовать недорогое хранилище для хранения фотографий и базу данных метаданных SQL для хранения таких сведений о фотографии, как uploaded_by, location, image_name, size, created_at и т. Д.

Вы должны быть в состоянии объяснить, как данные будут проходить через эти высокоуровневые компоненты, когда они будут у вас готовы.

Шаг 5. Разработка схемы базы данных

При проектировании БД мы решаем, какой тип базы данных подходит для нашего случая использования: SQL или NoSQL, а также сущности и отношения между ними.

Если мы создаем банковское приложение, в котором задействовано движение денег, мы не можем использовать базы данных NoSQL, которые в конечном итоге будут согласованными по своей природе.

Точно так же мы не можем использовать базу данных SQL, где данные меняются очень часто. В нашем примере с Instagram мы можем использовать базу данных NoSQL для хранения деталей метаданных для публикации.

Почему?

Поскольку у сообщения могут быть такие свойства, как лайки, image_url, created_at, created_by и т. Д. Но в будущем, допустим, мы хотим ввести другие функции, такие как дизлайк, теги и т. Д., Это можно легко сделать с помощью базы данных NoSQL без каких-либо изменений схемы.

Шаг 6. Дизайн класса

При проектировании классов мы придумываем низкоуровневые сущности классов, которые разделяют те же обязанности, отношения, операции, атрибуты и семантику.

Мы в основном перечисляем классы, их атрибуты, методы и их отношения с другими классами.

То, как вас будут оценивать, зависит от того, используете ли вы правильные объектно-ориентированные концепции, принципы и шаблоны проектирования. При разработке хорошей системы учитываются все эти аспекты: Абстракция, инкапсуляция, наследование и полиморфизм.

Также важно узнать о принципах SOLID (первые 5 принципов объектно-ориентированного дизайна). Эти принципы помогут вам разрабатывать программное обеспечение, которое будет легче поддерживать и расширять по мере его роста.

  • S - Принцип единоначалия
  • O - Принцип открытости-закрытости
  • L - Принцип замены Лискова
  • I - Принцип разделения интерфейса
  • D - Принцип инверсии зависимостей

Шаг 7. Кеширование

Кэш - это высокоскоростной уровень хранения данных в памяти, предназначенный для хранения данных для более быстрого доступа в будущем. Это средство повышения общей производительности системы. Кэширование важно в любой системе, которую необходимо масштабировать.

Мы в основном кэшируем часто используемые данные. Это приведет к тому, что приложениям потребуется меньше времени по сравнению с доступом к данным из базы данных каждый раз.

В нашем примере Instagram мы можем кэшировать метаданные фотографий, такие как created_by, location, created_at и т. Д., Поскольку эти параметры никогда не изменятся для данной фотографии. Другие параметры, такие как комментарии, лайки и т. Д., Нельзя кэшировать, так как они часто меняются.

В тот момент, когда мы начнем использовать кеш в нашем дизайне, нам также нужно подумать о политиках выселения. Поскольку кеши стоят дороже, чем хранилище базы данных, мы должны постоянно проверять объем данных, которые мы храним в кеше. Таким образом, выселение кеша становится важным.

Существует множество политик выселения, таких как LRU (Наименее недавно использовавшиеся), FIFO (Первым пришел - первым обслужен), LFU (Наименее часто используемым) и т. Д.

Шаг 8. Разделение / сегментирование данных

Часто бывает, что все данные в нашем приложении не могут храниться на одном сервере базы данных. В подобных случаях нам необходимо разработать стратегии для хранения данных на нескольких серверах баз данных.

Здесь мы в основном разбиваем большой набор данных на несколько фрагментов (логических разделов) и храним эти фрагменты на нескольких узлах.

Шардинг - хороший метод масштабирования растущего приложения.

Существует множество методов разделения данных:
1. Разделение на основе диапазона
2. Разделение на основе хеша
3. Разделение на основе каталогов
4. Вертикальное разделение и т. Д.

Вы должны прочитать об этом, чтобы понять, какие схемы разделения подходят для каких сценариев.

Этот восьмиступенчатый подход дает вам основу для решения любого вопроса системного проектирования. Но помните, что интервьюера может заинтересовать любой из этих шагов, и в этом случае вы сможете сосредоточиться только на этом шаге и выяснить детали.

Дополнительные советы

Система до масштабирования

Многие кандидаты пытаются сосредоточиться на создании масштабируемой системы еще до того, как у них появится проект работающей системы. Сосредоточьтесь на построении системы, а затем подумайте о ее масштабировании.

Начните с высокого уровня, а затем разверните

Начните с записи высокоуровневых компонентов, которые нам нужны для системы, которую мы строим. Затем перейдите к любому из компонентов более низкого уровня, которые предлагает интервьюер.

Это сохраняет ваш разум ясным и помогает разработать лучшую систему во время собеседования.

Назовите все свои предположения

Вы должны упомянуть все предположения, которые вы делаете во время собеседования. Важно, чтобы вы и интервьюер были на одной волне.

Учитывайте как функциональные, так и нефункциональные требования

При проектировании системы учитывайте как функциональные, так и нефункциональные требования.

Иногда становится трудно поддерживать нефункциональные требования, такие как согласованность, доступность, надежность данных и т. Д.

Основной алгоритм

Некоторым системам необходимо реализовать базовый алгоритм для работы системы. Например, если вы хотите разработать систему, подобную TinyURL, вам нужно придумать алгоритм для генерации крошечных URL-адресов для заданного длинного URL-адреса.

Не многие вопросы проектирования системы требуют реализации сложного алгоритма.

Дизайн в правильном масштабе

Одна и та же система может быть спроектирована совершенно по-разному в зависимости от необходимого масштаба. Итак, уточните масштаб, для которого вы проектируете систему, в начале обсуждения.

Рекомендуемые курсы для подготовки к собеседованию по системному дизайну:

Вот лучшие курсы, которые я рекомендую для подготовки к собеседованию по системному дизайну:

  1. Интервью по разработке системного дизайна
  2. Интервью по объектно-ориентированному дизайну
  3. Технические манекены Нарендра Л
  4. Системный дизайн Гаурав Сена
  5. Низкоуровневый дизайн | Code Mate

Заключение

  • Думайте о собеседовании по проектированию системы как о открытой дискуссии с вашим коллегой.
  • Невозможно придумать наилучшее решение для системы за отведенные 1–1,5 часа.
  • Уточните все требования и установите рамки для обсуждения.
  • Убедитесь, что вы и интервьюер находитесь на одной странице во время обсуждения.
  • Узнайте, как оценить объем данных, необходимый в следующие 5–10 лет, и спроектировать систему с учетом ожидаемой емкости.
  • Упомяните все предположения, которые вы делаете во время интервью.
  • Учитывая формулировку проблемы, попробуйте сначала подумать обо всех компонентах высокого уровня (службы, базы данных, кеши, очереди сообщений и т. Д.). Затем выясните детали системы нижнего уровня.
  • Важно научиться разрабатывать классы, базы данных и API.
  • Для собеседований по низкоуровневому дизайну важно изучить объектно-ориентированные и твердые принципы.
  • Интервьюер хочет знать, как вы подходите к данной проблеме и какой мыслительный процесс стоит за ней. Пока вы можете обосновать, почему компонент разработан определенным образом, вы хороши.
  • Практикуйтесь в решении проблем проектирования систем. Это единственный способ преуспеть в этом раунде.

Больше контента на plainenglish.io