Подготовка к интервью по системному дизайну (System Design Interview)

Часть 5. Продолжим проектировать сервис для сокращения URL на подобии TinyUrl.

Sergei Golitsyn
3 min readApr 28, 2020

Предыдущие статьи : Часть 1, Часть 2, Часть 3, Часть 4. Прежде чем читать эту статью, рекомендую прочитать предыдущие, в которых описываются основные этапы интервью по системному дизайну.

В прошлый раз мы закончили расчет размера хранилища и пропускной способности нашей системы. Давайте рассчитаем и оценим сколько памяти нам потребуется:

Оценка необходимой памяти:

Если мы захотим кэшировать некоторые «горячие» URL, к которым наиболее частый доступ, сколько памяти нам понадобится для этого? Если мы последуем правилу 80/20, подразумевающему что 20% URL генерируют 80% трафика, нам хотелось бы кэшировать эти 20% горячих URL.

Так как у нас 19К запросов в секунду,

мы получим 1.7 миллиардов запросов в день:

19K * 3600 seconds * 24 hours = ~1.7 billion

Что бы кэшировать 20% этих запросов,

нам потребуется 170GB памяти:

0.2 * 1.7 billion * 500 bytes =~ 170 GB

Высокоуровневая оценка:

Предполагая 500 миллионов новых URL в месяц и отношение 100:1 на чтение:запись, следующая таблица предоставляет высокоуровневую оценку нашего сервиса:

4. API системы

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

Мы можем использовать SOAP или REST API что бы определить/предоставить функциональность нашего сервиса. Ниже приведены определения API для создания и удаления URL.

createURL(api_dev_key, original_url, custom_alias=None, user_name=None, expire_date=None)

Параметры:

api_dev_key (string): Ключ API пользователя зарегистрировавшего аккаунт. Будет использоваться для различных вещей, типа распределения пользователей, основываясь на выделенной им квоте.
original_url (string): Оригинальный URL для сокращения.
custom_alias (string): (Не обязательно) пользовательский ключ для URL .

user_name (string): (Не обязательно) имя пользователя, для использования в шифровании.

expire_date (string): (Не обязательно) дата окончания срока жизни для короткого URL.

Возвращается строка:

Успешная вставка возвращает короткий URL, в других случаях возвращается код ошибки.

deleteUrl(api_dev_key, url_key)

Где url_key — это строковое представление короткого URL для удаления. Успешное удаление возвращает ‘URL Removed’.

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

Вредоносный пользователь может вывести нас из бизнеса, использовав все URL ключи в текущем диапазоне. Что бы предотвратить злоупотребление , мы можем ограничить пользователей по их api_dev_key. Каждый api_dev_key может быть ограничен определенным количеством URL для создания и перехода за какой то период времени(который может быть установлен различной длительности на каждый ключ)

5. Дизайн базы данных.

!!! Определение схемы базы данных данных на ранних этапах интервью будет помогать понимать как передаются данные между различными компонентами системы и позднее будет руководством для создания партиционирования (partitioning) данных !!!

Несколько наблюдений о характере данных, которые мы будем хранить:

1. Нам нужно хранить миллиарды записей

2. Каждый хранимый объект очень маленький

3. Нет никаких связей между записями, кроме информации о пользователе создавшем URL

4. Основная нагрузка на сервис — запросы на чтение

Нам потребуется две таблицы - одна для хранения информации о сопоставлениях URL и одна для пользовательской информации (кто создал короткую ссылку)

Какой тип базы данных мы должны использовать?

Так как мы ожидаем хранения миллиардов строк и мы не хотим использовать «отношения» между объектами NoSQL ключ-значение хранилище типа Dynamo или Cassandra — это лучший выбор. NoSQL решение будет легко масштабироваться.

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

--

--

Sergei Golitsyn

7+ years of experience in building massively scalable systems (mostly using Java) both from scratch and diving into an existing codebase.